Metadata-Version: 2.4
Name: agentropic
Version: 0.2.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: 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).

## Using MCP servers

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

agent = Agent(
    name="fs-agent",
    model="gpt-4o-mini",
    mcp_servers=[
        StdioServer(command="npx", args=["-y", "@modelcontextprotocol/server-filesystem", "."]),
    ],
)
print(await agent.arun("List the files in the current directory."))
```

Requires the optional MCP dependency: `pip install "agentropic[mcp]"`.

## 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`.
- **Streaming with tool calls**: `astream()` currently falls back to a
  non-streamed `arun()` when tools are registered — extend it if you need
  token-level streaming mid-tool-loop.
- **Multi-agent handoff**: compose multiple `Agent` instances and route
  between them yourself, or wrap one agent's `arun` as a tool for another.

