Catalog PyPI
PACKAGE EXPLORERView in registry

agentropic

PyPI

A minimal, hackable agentic framework: LLM calls via litellm, @tool-decorated functions, and MCP server support.

agentagentsailitellmllmmcptools
Versions collected1
Direct dependencies7From release 0.3.1
Last observed20 Oct, 23:13 UTC

README

Version 0.3.1 documentation

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, 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)

pip install agentropic

Quick start

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.

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

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.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.3.120 Oct 20267

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 23:13 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:063771eb48247597ec967a1072e3994ef360652ec4bbc0103e64ec22aa9cea15