AgentHub Python
AgentHub is a unified SDK for calling LLMs across providers with shared data models, tool calling, tracing, and playground support.
Installation
uv add agenthub-python
# or
pip install agenthub-python
For model IDs, API keys, and base URLs, see Model selection.
Basic Usage
This example asks GPT to call a weather tool, runs the tool, then sends the result back.
import asyncio
from agenthub import AutoLLMClient
def get_weather(location: str) -> str:
return f"Temperature in {location}: 22 C"
# Map tool names to their implementations so calls can be dispatched by name.
TOOLS = {"get_weather": get_weather}
async def main():
weather_function = {
"name": "get_weather",
"description": "Gets the current weather for a given location.",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city name"
}
},
"required": ["location"]
}
}
client = AutoLLMClient(model="gpt-5.5")
config = {"tools": [weather_function]}
tool_call = None
async for event in client.streaming_response_stateful(
message={
"role": "user",
"content_items": [{"type": "text", "text": "What's the weather in London?"}]
},
config=config
):
for item in event["content_items"]:
if item["type"] == "tool_call": # collected as the stream arrives; no second pass
tool_call = item
if tool_call:
# Dispatch by tool name instead of hardcoding the function.
result = TOOLS[tool_call["name"]](**tool_call["arguments"])
async for event in client.streaming_response_stateful(
message={
"role": "user",
"content_items": [
{
"type": "tool_result",
"text": result,
"tool_call_id": tool_call["tool_call_id"]
}
]
},
config=config
):
print(event)
# Streams the final answer token by token, then a stop event carrying usage:
# {'role': 'assistant', 'event_type': 'delta', 'content_items': [{'type': 'text', 'text': 'The'}], 'usage_metadata': None, 'finish_reason': None}
# {'role': 'assistant', 'event_type': 'delta', 'content_items': [{'type': 'text', 'text': ' weather'}], 'usage_metadata': None, 'finish_reason': None}
# {'role': 'assistant', 'event_type': 'delta', 'content_items': [{'type': 'text', 'text': ' is'}], 'usage_metadata': None, 'finish_reason': None}
# {'role': 'assistant', 'event_type': 'delta', 'content_items': [{'type': 'text', 'text': ' 22 C.'}], 'usage_metadata': None, 'finish_reason': None}
# {'role': 'assistant', 'event_type': 'stop', 'content_items': [], 'usage_metadata': {'cached_tokens': 0, 'prompt_tokens': 12, 'thoughts_tokens': 0, 'response_tokens': 8}, 'finish_reason': 'stop'}
asyncio.run(main())
Notes
Agent loop rules:
- Send every tool result with the exact
tool_call_idfrom its originatingtool_call. Do not invent, normalize, or reuse IDs across unrelated tool calls. - If streamed tool-call arguments cannot be parsed, AgentHub raises
ToolCallArgumentParseError. Do not execute the tool from partial arguments; let the agent runtime retry or re-prompt the model. - Preserve
thinkingandinline_thinkingitems. Do not strip or modifyfidelityfields. - Do not accumulate
usage_metadataacross events. Take the latestusage_metadataas the usage of the current request. - For embedding models, each
UniMessagein themessagesarray produces one embedding vector. Within a single message, all items incontent_itemsare aggregated into a single embedding. Setembedding_config.dimensionsin the config to control vector size.
Reference
- Model selection — model IDs, API keys, base URLs, and OpenAI-compatible routing.
- Data models —
UniConfig,UniMessage,UniEvent, and the tool-call streaming protocol. - APIs — client initialization and method signatures.
- Tracer & Playground — local tracing UI and the manual chat playground.