Metadata-Version: 2.5
Name: agentropic
Version: 0.3.1
Summary: A minimal, hackable agentic framework: LLM calls via litellm, @tool-decorated functions, and MCP server support.
Author-email: Vishal Tiwari <vishaltiwari.up2019@gmail.com>
License: MIT
License-File: LICENSE
Keywords: agent,agents,ai,litellm,llm,mcp,tools
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: litellm>=1.40.0
Requires-Dist: mcp>=1.0.0; python_version >= '3.10'
Requires-Dist: pydantic>=2.0.0
Provides-Extra: dev
Requires-Dist: build; extra == 'dev'
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: pytest-asyncio; extra == 'dev'
Requires-Dist: twine; extra == 'dev'
Provides-Extra: mcp
Requires-Dist: mcp>=1.0.0; extra == 'mcp'
Description-Content-Type: text/markdown

# agentropic

A small, hackable agentic framework in ~500 lines you fully own and can read
top to bottom in an afternoon:

- **LLM calls** go through [litellm](https://github.com/BerriAI/litellm), so you get
  every provider (OpenAI, Anthropic, Gemini, Ollama, Bedrock, 100+ more) for free.
- **`@tool` decorator** turns any python function into an LLM-callable tool with
  an auto-generated JSON schema (from type hints + docstring).
- **MCP support** — connect to any Model Context Protocol server (stdio or SSE)
  and its tools show up in your agent automatically, indistinguishable from
  local tools.
- **Agent loop** handles the call → tool-call → tool-result → call cycle for you,
  with memory, streaming, and a max-iteration safety valve.

## Install (once published)

```bash
pip install agentropic
```

## Quick start

```python
import asyncio
from agentropic import Agent, tool

@tool()
def get_weather(city: str) -> str:
    """Get the current weather for a city."""
    return f"It's sunny in {city}."

async def main():
    agent = Agent(
        name="assistant",
        model="gpt-4o-mini",         # any litellm model string
        instructions="You are helpful and concise.",
        tools=[get_weather],
    )
    print(await agent.arun("What's the weather in Paris?"))

asyncio.run(main())
```

Sync usage: `agent.run("...")` (wraps `arun` in `asyncio.run` for you).

## Streaming (`stream=True`)

Same shape as the OpenAI / Anthropic SDKs. Tool calls work while streaming.

```python
async for event in await agent.arun("Weather in Tokyo?", stream=True):
    if event.type == "text":
        print(event.text, end="", flush=True)
    elif event.type == "tool_call":
        print(f"\n[calling {event.tool_call.name}({event.tool_call.arguments})]")
    elif event.type == "tool_result":
        print(f"[-> {event.tool_call.result}]")
    elif event.type == "done":
        result = event.result          # full AgentRunResult (usage, tool_calls, ...)
```

With `verbose=True` (the default) the colourful terminal tracer already prints
tokens live, so only print `event.text` yourself when using `verbose=False`
(e.g. rendering into your own UI).

Sync: `for event in agent.run("...", stream=True): ...`
Text only: `async for token in agent.astream("..."): ...`

## Using MCP servers

```python
from agentropic import Agent
from agentropic.mcp import StdioServer, HTTPServer

agent = Agent(
    name="fs-agent",
    model="gpt-4o-mini",
    mcp_servers=[
        StdioServer(command="npx", args=["-y", "@modelcontextprotocol/server-filesystem", "."]),
        # HTTPServer(url="https://example.com/mcp", headers={"Authorization": "Bearer ..."}),
    ],
)

# Option A: connect once, keep servers alive across turns (recommended)
async with agent:
    print(await agent.arun("List the files in the current directory."))
    print(await agent.arun("Now read README.md"))

# Option B: no context manager — servers connect/disconnect around each run
print(await agent.arun("List the files in the current directory."))
```

Requires the optional MCP dependency: `pip install "agentropic[mcp]"`, plus whatever
the server itself needs (e.g. Node.js for `npx` servers). Transports: `StdioServer`,
`HTTPServer` (streamable HTTP), `SSEServer` (legacy SSE).

## Architecture

```
src/agentropic/
├── __init__.py     # public API surface
├── agent.py         # the run loop: LLM <-> tools <-> memory
├── llm.py            # thin litellm wrapper (swap providers here)
├── tools.py           # @tool decorator, Tool, ToolRegistry, schema generation
├── memory.py           # in-memory conversation history (swap for your own store)
└── mcp/
    └── client.py        # MCP stdio/SSE client -> Tool adapter
```

Everything is a plain, editable python file — no hidden magic, no plugin
registry you can't inspect. Read `agent.py` first; that's the whole loop.

## Extending it

- **Custom memory / persistence**: implement `.add()`, `.get()`, `.clear()`
  matching `Memory` and pass `memory=YourMemory()` to `Agent`.
- **Multi-agent handoff**: compose multiple `Agent` instances and route
  between them yourself, or wrap one agent's `arun` as a tool for another.

