uni-agent 0.1.1
Unified Agent SDK
License: MIT
Requires Python: >=3.9
Keywords: ai, agent, llm, claude, openai, gemini, langchain, unified-api

# UniAgent

UniAgent provides a unified agent SDK that normalizes LLM inputs/outputs to a
Claude-compatible canonical protocol, with driver adapters for multiple model
providers and built-in middleware/observability hooks.

## Installation

```bash
pip install -e .
```

Optional observability support:

```bash
pip install -e .[otel]
```

## Quick Start

```python
import os

from uniagent import UniAgent

agent = UniAgent(
    provider="claude",
    model="claude-sonnet-4-5-20250929",
    api_key=os.getenv("ANTHROPIC_API_KEY"),
)

response = await agent.run([agent.user("Hello")])

print(response)
```

## Tool Registration

```python
from uniagent import UniAgent

@UniAgent.tool
def get_weather(city: str) -> str:
    """Get weather for a city."""
    return f"Sunny in {city}"

agent = UniAgent(
    provider="claude",
    model="claude-sonnet-4-5-20250929",
    api_key="YOUR_ANTHROPIC_API_KEY",
    tools=[get_weather],
)
```

## Streaming

```python
async for event in agent.stream(messages):
    print(event.event, event.data)
```

## Provider Examples

### Anthropic Claude (Unified Factory)

```python
import asyncio
import os

from uniagent import UniAgent


@UniAgent.tool
def get_weather(city: str) -> str:
    """Get weather for a city."""
    return f"Sunny in {city}"


async def main() -> None:
    agent = UniAgent(
        provider="claude",
        model="claude-sonnet-4-5-20250929",
        api_key=os.getenv("ANTHROPIC_API_KEY"),
        tools=[get_weather],
    )

    response = await agent.run(
        [agent.user("Weather in Tokyo?")],
        config={"max_tokens": 256, "enable_betas": ["structured-outputs-2025-11-13"]},
    )
    print(response)


if __name__ == "__main__":
    asyncio.run(main())
```

### Google Gemini (Unified Factory)

```python
import asyncio
import os

from uniagent import UniAgent


@UniAgent.tool
def multiply(a: int, b: int) -> int:
    """Multiply two integers."""
    return a * b


async def main() -> None:
    agent = UniAgent(
        provider="gemini",
        model="gemini-1.5-pro",
        api_key=os.getenv("GOOGLE_API_KEY"),
        tools=[multiply],
    )

    response = await agent.run(
        [agent.user("2 * 21")],
        config={"generation_config": {"max_output_tokens": 256}},
    )
    print(response)


if __name__ == "__main__":
    asyncio.run(main())
```

### OpenAI (Unified Factory)

```python
import asyncio
import os

from uniagent import UniAgent


async def main() -> None:
    agent = UniAgent(
        provider="openai",
        model="gpt-5.2",
        api_key=os.getenv("OPENAI_API_KEY"),
    )

    response = await agent.run([agent.user("Hello")])
    print(response)


if __name__ == "__main__":
    asyncio.run(main())
```

### DeepAgents / LangGraph (Unified Factory)

```python
import asyncio
from typing import Dict, List

from uniagent import UniAgent


def build_graph():
    from langgraph.graph import END, StateGraph

    class State(Dict):
        messages: List[UniAgent.Message]

    def final_node(state: State) -> str:
        return "DeepAgent output"

    graph = StateGraph(State)
    graph.add_node("final", final_node)
    graph.set_entry_point("final")
    graph.add_edge("final", END)
    return graph.compile()


async def main() -> None:
    agent = UniAgent(
        provider="deep_agent",
        graph_builder="examples.deep_agent_basic:build_graph",
    )

    response = await agent.run([agent.user("Run the graph")])
    print(response)


if __name__ == "__main__":
    asyncio.run(main())
```