Documentation Index
Fetch the complete documentation index at: https://docs.sudoiq.com/llms.txt
Use this file to discover all available pages before exploring further.
Tools have two parts that must stay aligned:
- Server registry: JSON schema metadata so models know tool names and arguments.
- App-defined tool: your code that runs when the model asks to call that tool.
This guide covers both the registration step and the runtime handler contract for SSE and webhook flows.
This example defines a parse_pdf tool with a single required string argument file_path.
from agentsapi.models.tools import ToolDefinition, ParametersSchema, ParameterProperty
definitions = [
ToolDefinition(
name="parse_pdf",
namespace="main",
description="Extract text from a PDF given file_path.",
schema_data=ParametersSchema(
properties={
"file_path": ParameterProperty(
type="string",
description="Reference from run-input store or path.",
),
},
required=["file_path"],
),
),
]
await client.tools.register_tools(definitions)
page = await client.tools.get_tools(namespace="main", limit=50)
Use listing to confirm registration or to debug missing-tool errors during runs.
For Python integrations, handlers use this signature:
- Signature:
async def tool(args: dict, agent_id: str, task_id: int) -> str
- Return: a string. For structured output, return JSON text (for example
json.dumps({...})).
Why all three inputs matter:
args: model-supplied arguments for that tool call.
agent_id: which workflow invoked the tool (lets one handler support multiple agents).
task_id: the specific run id for logging, tracing, and run-scoped lookups.
SSE runtime path
For streaming runs, register handlers with set_tools before execute_agent / run_agent. The client invokes them automatically when the run pauses for tool calls.
import json
async def parse_pdf(args: dict, agent_id: str, task_id: int) -> str:
path = (args or {}).get("file_path", "")
# ... read the file reference and extract text ...
return json.dumps({"text": "..."})
client.set_tools({
"parse_pdf": (None, parse_pdf),
})
Webhook runtime path
If you run with webhooks, parse webhook payloads and submit tool responses explicitly:
tool_results = await client.process_webhook_tools(request, tools_map)
await client.send_tool_responses(request.agent_id, request.task_id, tool_results.results)
Minimal sketch:
from agentsapi import AgentGraphRunStatusResponse
async def handle_agent_webhook(body: dict, client):
request = AgentGraphRunStatusResponse.model_validate(body)
if request.status != "awaiting_tool_calls":
return {"ok": True}
tool_results = await client.process_webhook_tools(request, {
"parse_pdf": (None, parse_pdf),
})
await client.send_tool_responses(
request.agent_id,
request.task_id,
tool_results.results,
)
return {"ok": True, "status": "tool_responses_sent"}
Do not use polling loops to discover tool calls; use SSE or webhooks as documented.
See also