composio-sdk 0.2.0

Minimal Rust SDK for Composio Tool Router REST API
Documentation
# Provider System - Guia Visual


## 🎬 Fluxo Completo: Do Composio ao Framework


```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 1. COMPOSIO CORE - Formato Universal                                β”‚
β”‚                                                                      β”‚
β”‚   Tool {                                                             β”‚
β”‚     slug: "GITHUB_CREATE_ISSUE"                                      β”‚
β”‚     description: "Create a GitHub issue"                             β”‚
β”‚     input_parameters: {                                              β”‚
β”‚       type: "object",                                                β”‚
β”‚       properties: {                                                  β”‚
β”‚         owner: {type: "string"},                                     β”‚
β”‚         repo: {type: "string"},                                      β”‚
β”‚         title: {type: "string"}                                      β”‚
β”‚       }                                                              β”‚
β”‚     }                                                                β”‚
β”‚   }                                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β”‚
                           β”‚ provider.wrap_tool(tool)
                           β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚                                     β”‚
        β–Ό                                     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 2A. OPENAI FORMAT     β”‚          β”‚ 2B. ANTHROPIC FORMAT   β”‚
β”‚                       β”‚          β”‚                        β”‚
β”‚ ChatCompletionTool {  β”‚          β”‚ Tool {                 β”‚
β”‚   type: "function",   β”‚          β”‚   name: "GITHUB_...",  β”‚
β”‚   function: {         β”‚          β”‚   description: "...",  β”‚
β”‚     name: "GITHUB_...",β”‚         β”‚   input_schema: {      β”‚
β”‚     description: "...",β”‚         β”‚     type: "object",    β”‚
β”‚     parameters: {...} β”‚          β”‚     properties: {...}  β”‚
β”‚   }                   β”‚          β”‚   }                    β”‚
β”‚ }                     β”‚          β”‚ }                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

---

## πŸ”„ Ciclo de Vida: NonAgentic vs Agentic


### NonAgentic (Controle Manual)


```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 1. Developerβ”‚
β”‚   Calls SDK β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β”‚ composio.tools.get(user_id, toolkits=["github"])
       β”‚
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 2. Provider      β”‚
β”‚   Converts Tools β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β”‚ Returns: [ChatCompletionToolParam, ...]
       β”‚
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 3. Developer     β”‚
β”‚   Passes to LLM  β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β”‚ openai.chat.completions.create(tools=tools)
       β”‚
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 4. LLM           β”‚
β”‚   Returns        β”‚
β”‚   Tool Calls     β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β”‚ response.choices[0].message.tool_calls
       β”‚
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 5. Developer     β”‚
β”‚   MANUALLY       β”‚
β”‚   Executes Tools β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β”‚ for tool_call in tool_calls:
       β”‚     composio.tools.execute(...)
       β”‚
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 6. Composio      β”‚
β”‚   Executes &     β”‚
β”‚   Returns Result β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β”‚ {data: {...}, error: null, successful: true}
       β”‚
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 7. Developer     β”‚
β”‚   Sends Results  β”‚
β”‚   Back to LLM    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

### Agentic (AutomΓ‘tico)


```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 1. Developerβ”‚
β”‚   Calls SDK β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β”‚ composio.tools.get(user_id, toolkits=["github"])
       β”‚
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 2. Provider      β”‚
β”‚   Converts Tools β”‚
β”‚   + Injects      β”‚
β”‚   Execute Fn     β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β”‚ Returns: [FunctionTool(on_invoke=execute_fn), ...]
       β”‚
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 3. Developer     β”‚
β”‚   Passes to      β”‚
β”‚   Agent          β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β”‚ agent = Agent(tools=tools)
       β”‚ agent.run("Create issue")
       β”‚
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 4. Framework Loop (AUTOMATIC)                    β”‚
β”‚                                                   β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚   β”‚ a. Call LLM                         β”‚        β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                β”‚                                  β”‚
β”‚                β–Ό                                  β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚   β”‚ b. Detect Tool Calls                β”‚        β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                β”‚                                  β”‚
β”‚                β–Ό                                  β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚   β”‚ c. AUTOMATICALLY Execute            β”‚        β”‚
β”‚   β”‚    (calls on_invoke_tool)           β”‚        β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                β”‚                                  β”‚
β”‚                β–Ό                                  β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚   β”‚ d. Send Results Back to LLM         β”‚        β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                β”‚                                  β”‚
β”‚                β–Ό                                  β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚   β”‚ e. Repeat Until Task Complete       β”‚        β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β”‚ Final result
       β”‚
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 5. Developer     β”‚
β”‚   Gets Final     β”‚
β”‚   Result         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

---

## 🎭 Exemplo PrÑtico: Mesma Tarefa, Diferentes Providers


### Tarefa: "Create a GitHub issue titled 'Bug fix'"


#### OpenAI Provider (NonAgentic)


```python
# Setup

composio = Composio(provider=OpenAIProvider())
tools = composio.tools.get(user_id="user_123", toolkits=["github"])

# Step 1: Call LLM

response = openai.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "Create issue 'Bug fix'"}],
    tools=tools  # ← [ChatCompletionToolParam, ...]
)

# Step 2: Extract tool calls

tool_call = response.choices[0].message.tool_calls[0]
# {

#   id: "call_123",

#   function: {

#     name: "GITHUB_CREATE_ISSUE",

#     arguments: '{"owner":"composio","repo":"composio","title":"Bug fix"}'

#   }

# }


# Step 3: Execute manually

result = composio.tools.execute(
    slug=tool_call.function.name,
    arguments=json.loads(tool_call.function.arguments),
    user_id="user_123"
)

# Step 4: Send back to LLM

final_response = openai.chat.completions.create(
    model="gpt-4",
    messages=[
        {"role": "user", "content": "Create issue 'Bug fix'"},
        response.choices[0].message,
        {"role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(result)}
    ]
)
```

#### OpenAI Agents Provider (Agentic)


```python
# Setup

composio = Composio(provider=OpenAIAgentsProvider())
tools = composio.tools.get(user_id="user_123", toolkits=["github"])

# One call - framework handles everything!

agent = Agent(model="gpt-4", tools=tools)
result = agent.run("Create issue 'Bug fix'")

# ↑ Framework automatically:

# 1. Calls LLM

# 2. Detects tool call

# 3. Executes GITHUB_CREATE_ISSUE (via on_invoke_tool)

# 4. Sends result back to LLM

# 5. Returns final response

```

---

## πŸ” Anatomia de um Provider


### Estrutura Completa


```python
class MyCustomProvider(NonAgenticProvider[MyTool, List[MyTool]], name="my_provider"):
    """
    Custom provider for MyFramework
    """
    
    # 1. REQUIRED: Convert single tool
    def wrap_tool(self, tool: Tool) -> MyTool:
        return MyTool(
            name=tool.slug,
            description=tool.description,
            schema=tool.input_parameters
        )
    
    # 2. REQUIRED: Convert multiple tools
    def wrap_tools(self, tools: Sequence[Tool]) -> List[MyTool]:
        return [self.wrap_tool(tool) for tool in tools]
    
    # 3. OPTIONAL: Helper methods
    def handle_tool_calls(self, response: MyResponse) -> List[ToolExecutionResponse]:
        """Extract and execute tool calls from framework response"""
        results = []
        for call in response.tool_calls:
            result = self.execute_tool(  # ← Injected by SDK
                slug=call.name,
                arguments=call.arguments,
                user_id=self.user_id
            )
            results.append(result)
        return results
    
    # 4. OPTIONAL: Framework-specific optimizations
    def optimize_schema(self, schema: dict) -> dict:
        """Optimize schema for framework requirements"""
        # Remove unsupported fields
        # Add framework-specific fields
        return optimized_schema
```

---

## πŸ“Š Matriz de Compatibilidade


| Framework | Provider Type | Auto Execute | Helper Methods | Status |
|-----------|---------------|--------------|----------------|--------|
| OpenAI Chat | NonAgentic | ❌ | `handle_tool_calls` | βœ… Stable |
| OpenAI Responses | NonAgentic | ❌ | `handle_tool_calls` | βœ… Stable |
| OpenAI Agents | Agentic | βœ… | - | βœ… Stable |
| Anthropic | NonAgentic | ❌ | `handle_tool_calls` | βœ… Stable |
| Google Gemini | NonAgentic | ❌ | `handle_tool_calls` | βœ… Stable |
| LangChain | Agentic | βœ… | - | βœ… Stable |
| CrewAI | Agentic | βœ… | - | βœ… Stable |
| AutoGen | Agentic | βœ… | - | βœ… Stable |
| LlamaIndex | Agentic | βœ… | - | βœ… Stable |

---

## 🎯 Decisão: Qual Provider Usar?


```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ VocΓͺ quer controlar o loop de execuΓ§Γ£o?β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
      β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”
      β”‚             β”‚
     SIM           NÃO
      β”‚             β”‚
      β–Ό             β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ NonAgentic  β”‚  β”‚  Agentic     β”‚
β”‚             β”‚  β”‚              β”‚
β”‚ - OpenAI    β”‚  β”‚ - OpenAI     β”‚
β”‚   Chat      β”‚  β”‚   Agents     β”‚
β”‚ - Anthropic β”‚  β”‚ - LangChain  β”‚
β”‚ - Gemini    β”‚  β”‚ - CrewAI     β”‚
β”‚             β”‚  β”‚ - AutoGen    β”‚
β”‚             β”‚  β”‚              β”‚
β”‚ VocΓͺ:       β”‚  β”‚ Framework:   β”‚
β”‚ β€’ Chama LLM β”‚  β”‚ β€’ Chama LLM  β”‚
β”‚ β€’ Executa   β”‚  β”‚ β€’ Executa    β”‚
β”‚ β€’ Controla  β”‚  β”‚ β€’ Controla   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

---

## πŸ’‘ Dicas de ImplementaΓ§Γ£o


### 1. ComeΓ§ar Simples


```rust
// ImplementaΓ§Γ£o mΓ­nima
pub trait Provider {
    type Tool;
    type ToolCollection;
    
    fn wrap_tool(&self, tool: &ToolSchema) -> Self::Tool;
    fn wrap_tools(&self, tools: Vec<ToolSchema>) -> Self::ToolCollection;
}
```

### 2. Adicionar Helpers Gradualmente


```rust
// Adicionar mΓ©todos opcionais conforme necessΓ‘rio
pub trait ProviderHelpers: Provider {
    fn handle_tool_calls(&self, response: Response) -> Vec<ToolExecutionResponse> {
        // Default implementation
        vec![]
    }
}
```

### 3. Usar Associated Types


```rust
// Melhor que generics para este caso
pub trait Provider {
    type Tool: Serialize;  // ← Associated type
    type ToolCollection: IntoIterator<Item = Self::Tool>;
    
    // MΓ©todos usam Self::Tool automaticamente
    fn wrap_tool(&self, tool: &ToolSchema) -> Self::Tool;
}
```

---

## πŸš€ PrΓ³ximos Passos


1. **Implementar trait base** em Rust
2. **Criar OpenAIProvider** como referΓͺncia
3. **Testar com cliente genΓ©rico**
4. **Adicionar mais providers** conforme demanda
5. **Documentar padrΓ΅es** para contribuidores

O Provider System Γ© a fundaΓ§Γ£o para um SDK verdadeiramente universal! πŸŽ‰