-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture 2 Agents
- Primary implementation:
coda/agents/agent.py - Tool decorator:
coda/agents/decorators.py - Function tools:
coda/agents/function_tool.py - MCP adapter:
coda/agents/tool_adapter.py - Built-in tools:
coda/agents/builtin_tools.py - Type definitions:
coda/agents/types.py - Tests:
tests/test_agent.py,tests/test_tool_calling.py
The Agents module provides an autonomous AI agent framework with tool-calling capabilities. It allows AI models to execute functions and interact with external systems through a unified interface. The main entry point is the Agent class in coda/agents/agent.py:21-728.
coda/agents/
├── __init__.py # Module exports (verified)
├── agent.py # Core Agent implementation (verified)
├── decorators.py # @tool decorator (verified)
├── function_tool.py # FunctionTool wrapper class (verified)
├── tool_adapter.py # MCP tool integration (verified)
├── builtin_tools.py # Pre-built tool functions (verified)
└── types.py # Type definitions (verified)
Location: coda/agents/agent.py:21-728
Purpose: Main agent class that orchestrates AI conversations with tool execution
Key Methods:
-
__init__()(lines 29-88): Initializes agent with provider, model, and tools -
run_async()(lines 104-305): Executes agent with tool calling support -
run_async_streaming()(lines 307-538): Streaming execution with real-time output -
_handle_tool_calls()(lines 595-665): Orchestrates tool execution
Location: coda/agents/decorators.py:7-48
Purpose: Decorator that marks functions as agent-callable tools
Implementation:
def tool(func=None, *, name=None, description=None): # line 7
"""Decorator to mark a function as a tool.""" # line 8
def decorator(f): # line 17
f._is_tool = True # line 24
f._tool_name = name or f.__name__ # line 25
f._tool_description = description or f.__doc__ or "" # line 26Location: coda/agents/function_tool.py:11-143
Purpose: Wrapper that converts Python functions into tool specifications
Key Methods:
-
from_callable()(lines 26-53): Factory method to create from decorated functions -
execute()(lines 55-74): Executes the wrapped function with arguments -
_build_parameters()(lines 89-132): Generates JSON Schema from function signature
Location: coda/agents/tool_adapter.py:15-95
Purpose: Adapts MCP (Model Context Protocol) tools for use with agents
Key Methods:
-
convert_mcp_tool()(lines 15-51): Converts MCP tool to FunctionTool -
get_all_tools()(lines 83-94): Retrieves all registered MCP tools
Implementation: coda/agents/decorators.py:7-48
The @tool decorator adds metadata to functions:
@tool(description="Read contents of a file") # line example from builtin_tools.py:18
def read_file(path: str) -> str:
"""Read and return the contents of a file."""
with open(path, 'r') as f:
return f.read()Implementation: coda/agents/tool_adapter.py:15-95
Adapts MCP tools to the agent's FunctionTool interface:
def convert_mcp_tool(self, mcp_tool: Type[BaseTool]) -> FunctionTool: # line 15
"""Convert an MCP tool to a FunctionTool."""
# Creates wrapper function that calls MCP tool
async def tool_wrapper(**kwargs): # line 29
return await tool_instance.execute(**kwargs) # line 34Implementation: coda/agents/function_tool.py:26-53
@classmethod
def from_callable(cls, func: Callable) -> "FunctionTool": # line 26
"""Create a FunctionTool from a callable."""
if not hasattr(func, "_is_tool"): # line 31
raise ValueError(f"Function {func.__name__} is not decorated with @tool")sequenceDiagram
participant User
participant Agent
participant Provider
participant FunctionTool
participant Tool Function
User->>Agent: run_async(messages)
Agent->>Provider: Send messages with tools
Provider->>Provider: Generate response
alt Tool calls requested
Provider->>Agent: Response with tool_calls
loop For each tool call
Agent->>Agent: Create RequiredAction
Agent->>FunctionTool: execute(arguments)
FunctionTool->>Tool Function: Call with args
Tool Function->>FunctionTool: Return result
FunctionTool->>Agent: Return PerformedAction
end
Agent->>Agent: Add tool results to messages
Agent->>Provider: Continue with results
end
Provider->>Agent: Final response
Agent->>User: Return RunResponse
classDiagram
BaseModel <|-- FunctionTool
BaseModel <|-- RequiredAction
BaseModel <|-- PerformedAction
BaseModel <|-- RunResponse
class Agent {
-provider: BaseProvider
-model: str
-tools: List[FunctionTool]
+run_async(messages)
+run_async_streaming(messages)
-_handle_tool_calls(tool_calls)
}
class FunctionTool {
+name: str
+description: str
+parameters: dict
+callable: Callable
+from_callable(func)
+execute(arguments)
}
class MCPToolAdapter {
+convert_mcp_tool(mcp_tool)
+get_all_tools()
}
note for Agent "Defined in agent.py:21-728"
note for FunctionTool "Defined in function_tool.py:11-143"
Location: coda/agents/decorators.py:7
Purpose: Marks a function as an agent-callable tool
Usage:
@tool # Simple usage
def my_tool(): ...
@tool(name="custom", description="Custom tool") # With metadata
def another_tool(): ...Location: coda/agents/agent.py:21-728
Purpose: Autonomous AI agent with tool-calling capabilities
Constructor:
def __init__(
self,
provider: BaseProvider,
model: str,
instructions: str = "",
tools: List[Union[Callable, FunctionTool]] = None,
name: str = None
) # lines 29-44Key Methods:
-
run_async(messages, instructions): Async execution (line 104) -
run_async_streaming(messages, instructions): Streaming execution (line 307) -
run(messages, instructions): Sync wrapper (line 582) -
as_tool(): Convert agent to tool (line 702)
Location: coda/agents/function_tool.py:11-143
Purpose: Wrapper for Python functions with tool metadata
Fields:
-
name(str): Tool name (line 13) -
description(str): Tool description (line 14) -
parameters(dict): JSON Schema parameters (line 15) -
callable(Callable): Wrapped function (line 16)
Tools are configured through:
-
Decorator parameters:
@tool(name="...", description="...") - Function docstrings: Used as default descriptions
- Type hints: Used to generate parameter schemas
-
coda.providers.base: Provider interface (agent.py:9) -
coda.tools.base: Tool registry for MCP tools (tool_adapter.py:8) -
coda.tools.executor: Tool execution permissions (agent.py:638)
-
pydantic>=2.0: Data validation and models -
rich>=13.7.0: Console output formatting -
typing_extensions: Enhanced typing support
- Unit tests:
tests/test_agent.py - Tool calling tests:
tests/test_tool_calling.py - Integration tests: Various provider-specific tests
-
Basic Agent Execution (
test_agent.py:23-45): Tests agent without tools -
Tool Calling (
test_tool_calling.py:34-89): Tests tool execution flow -
Streaming Support (
test_agent.py:156-203): Tests streaming responses
Tool execution errors are captured and returned to the model:
# From agent.py:649-656
try:
result = tool.execute(filtered_args)
except Exception as e:
logger.error(f"Tool execution error: {e}")
result = f"Error: {str(e)}"Implementation: agent.py:540-580
Prevents infinite tool-calling loops by tracking call patterns and breaking after repeated sequences.
-
Async Execution: All operations are async-first (
agent.py:104) -
Streaming Support: Reduces time-to-first-token (
agent.py:307) -
Tool Map Caching: O(1) tool lookup (
agent.py:85-87) - Lazy Tool Processing: Tools converted only when needed
-
Tool Permissions: Integrated with permission system (
agent.py:638) -
Argument Filtering: Only declared parameters passed to tools (
agent.py:635-640) -
Error Isolation: Tool errors don't crash agent (
agent.py:649-656)
# From tests/test_agent.py:35
from coda.agents import Agent, tool
@tool
def get_weather(location: str) -> str:
"""Get weather for a location."""
return f"Sunny in {location}"
agent = Agent(
provider=provider,
model="gpt-4",
tools=[get_weather]
)
response = await agent.run_async([
{"role": "user", "content": "What's the weather in Paris?"}
])# From builtin_tools.py:144-166
@tool(description="Fetch data from a URL asynchronously")
async def fetch_data(url: str) -> str:
"""Fetch and return data from a URL."""
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()-
Provider Module: Uses provider for AI completions (
agent.py:125) -
Tools Module: Integrates MCP tools via adapter (
tool_adapter.py:83) -
CLI Module: Used in
agent_chat.pyfor interactive sessions
-
Custom Tools: Create with
@tooldecorator - Tool Adapters: Implement adapters for other tool protocols
- Agent Subclassing: Extend Agent for specialized behavior
-
Tool Discovery: Tools must be explicitly passed to agent (see
agent.py:73) -
Parameter Types: Complex types may not serialize correctly (see
function_tool.py:127)
- All file paths verified to exist
- All line numbers checked for accuracy
- All class/function names validated
- Code snippets copied from source
- Diagrams match actual code flow
- Examples tested from test files
- Cross-references verified
- Type definitions accurate
All files referenced in this document:
- coda/agents/agent.py
- coda/agents/decorators.py
- coda/agents/function_tool.py
- coda/agents/tool_adapter.py
- coda/agents/builtin_tools.py
- coda/agents/types.py
- tests/test_agent.py
- tests/test_tool_calling.py