agentropic 0.2.2__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
- __pycache__/
2
- *.pyc
3
- .venv/
4
- venv/
5
- dist/
6
- build/
7
- *.egg-info/
8
- .pytest_cache/
9
- .env
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ venv/
5
+ dist/
6
+ build/
7
+ *.egg-info/
8
+ .pytest_cache/
9
+ .env
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Your Name
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Your Name
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: agentropic
3
- Version: 0.2.2
3
+ Version: 0.3.0
4
4
  Summary: A minimal, hackable agentic framework: LLM calls via litellm, @tool-decorated functions, and MCP server support.
5
5
  Author-email: Vishal Tiwari <vishaltiwari.up2019@gmail.com>
6
6
  License: MIT
@@ -70,23 +70,52 @@ asyncio.run(main())
70
70
 
71
71
  Sync usage: `agent.run("...")` (wraps `arun` in `asyncio.run` for you).
72
72
 
73
+ ## Streaming (`stream=True`)
74
+
75
+ Same shape as the OpenAI / Anthropic SDKs. Tool calls work while streaming.
76
+
77
+ ```python
78
+ async for event in await agent.arun("Weather in Tokyo?", stream=True):
79
+ if event.type == "text":
80
+ print(event.text, end="", flush=True)
81
+ elif event.type == "tool_call":
82
+ print(f"\n[calling {event.tool_call.name}({event.tool_call.arguments})]")
83
+ elif event.type == "tool_result":
84
+ print(f"[-> {event.tool_call.result}]")
85
+ elif event.type == "done":
86
+ result = event.result # full AgentRunResult (usage, tool_calls, ...)
87
+ ```
88
+
89
+ Sync: `for event in agent.run("...", stream=True): ...`
90
+ Text only: `async for token in agent.astream("..."): ...`
91
+
73
92
  ## Using MCP servers
74
93
 
75
94
  ```python
76
95
  from agentropic import Agent
77
- from agentropic.mcp import StdioServer
96
+ from agentropic.mcp import StdioServer, HTTPServer
78
97
 
79
98
  agent = Agent(
80
99
  name="fs-agent",
81
100
  model="gpt-4o-mini",
82
101
  mcp_servers=[
83
102
  StdioServer(command="npx", args=["-y", "@modelcontextprotocol/server-filesystem", "."]),
103
+ # HTTPServer(url="https://example.com/mcp", headers={"Authorization": "Bearer ..."}),
84
104
  ],
85
105
  )
106
+
107
+ # Option A: connect once, keep servers alive across turns (recommended)
108
+ async with agent:
109
+ print(await agent.arun("List the files in the current directory."))
110
+ print(await agent.arun("Now read README.md"))
111
+
112
+ # Option B: no context manager — servers connect/disconnect around each run
86
113
  print(await agent.arun("List the files in the current directory."))
87
114
  ```
88
115
 
89
- Requires the optional MCP dependency: `pip install "agentropic[mcp]"`.
116
+ Requires the optional MCP dependency: `pip install "agentropic[mcp]"`, plus whatever
117
+ the server itself needs (e.g. Node.js for `npx` servers). Transports: `StdioServer`,
118
+ `HTTPServer` (streamable HTTP), `SSEServer` (legacy SSE).
90
119
 
91
120
  ## Architecture
92
121
 
@@ -108,9 +137,6 @@ registry you can't inspect. Read `agent.py` first; that's the whole loop.
108
137
 
109
138
  - **Custom memory / persistence**: implement `.add()`, `.get()`, `.clear()`
110
139
  matching `Memory` and pass `memory=YourMemory()` to `Agent`.
111
- - **Streaming with tool calls**: `astream()` currently falls back to a
112
- non-streamed `arun()` when tools are registered — extend it if you need
113
- token-level streaming mid-tool-loop.
114
140
  - **Multi-agent handoff**: compose multiple `Agent` instances and route
115
141
  between them yourself, or wrap one agent's `arun` as a tool for another.
116
142
 
@@ -44,23 +44,52 @@ asyncio.run(main())
44
44
 
45
45
  Sync usage: `agent.run("...")` (wraps `arun` in `asyncio.run` for you).
46
46
 
47
+ ## Streaming (`stream=True`)
48
+
49
+ Same shape as the OpenAI / Anthropic SDKs. Tool calls work while streaming.
50
+
51
+ ```python
52
+ async for event in await agent.arun("Weather in Tokyo?", stream=True):
53
+ if event.type == "text":
54
+ print(event.text, end="", flush=True)
55
+ elif event.type == "tool_call":
56
+ print(f"\n[calling {event.tool_call.name}({event.tool_call.arguments})]")
57
+ elif event.type == "tool_result":
58
+ print(f"[-> {event.tool_call.result}]")
59
+ elif event.type == "done":
60
+ result = event.result # full AgentRunResult (usage, tool_calls, ...)
61
+ ```
62
+
63
+ Sync: `for event in agent.run("...", stream=True): ...`
64
+ Text only: `async for token in agent.astream("..."): ...`
65
+
47
66
  ## Using MCP servers
48
67
 
49
68
  ```python
50
69
  from agentropic import Agent
51
- from agentropic.mcp import StdioServer
70
+ from agentropic.mcp import StdioServer, HTTPServer
52
71
 
53
72
  agent = Agent(
54
73
  name="fs-agent",
55
74
  model="gpt-4o-mini",
56
75
  mcp_servers=[
57
76
  StdioServer(command="npx", args=["-y", "@modelcontextprotocol/server-filesystem", "."]),
77
+ # HTTPServer(url="https://example.com/mcp", headers={"Authorization": "Bearer ..."}),
58
78
  ],
59
79
  )
80
+
81
+ # Option A: connect once, keep servers alive across turns (recommended)
82
+ async with agent:
83
+ print(await agent.arun("List the files in the current directory."))
84
+ print(await agent.arun("Now read README.md"))
85
+
86
+ # Option B: no context manager — servers connect/disconnect around each run
60
87
  print(await agent.arun("List the files in the current directory."))
61
88
  ```
62
89
 
63
- Requires the optional MCP dependency: `pip install "agentropic[mcp]"`.
90
+ Requires the optional MCP dependency: `pip install "agentropic[mcp]"`, plus whatever
91
+ the server itself needs (e.g. Node.js for `npx` servers). Transports: `StdioServer`,
92
+ `HTTPServer` (streamable HTTP), `SSEServer` (legacy SSE).
64
93
 
65
94
  ## Architecture
66
95
 
@@ -82,9 +111,6 @@ registry you can't inspect. Read `agent.py` first; that's the whole loop.
82
111
 
83
112
  - **Custom memory / persistence**: implement `.add()`, `.get()`, `.clear()`
84
113
  matching `Memory` and pass `memory=YourMemory()` to `Agent`.
85
- - **Streaming with tool calls**: `astream()` currently falls back to a
86
- non-streamed `arun()` when tools are registered — extend it if you need
87
- token-level streaming mid-tool-loop.
88
114
  - **Multi-agent handoff**: compose multiple `Agent` instances and route
89
115
  between them yourself, or wrap one agent's `arun` as a tool for another.
90
116
 
@@ -31,7 +31,7 @@ async def main():
31
31
  tools=[get_weather, add],
32
32
  # Optional: pull in tools from a live MCP server too.
33
33
  # mcp_servers=[StdioServer(command="npx", args=["-y", "@modelcontextprotocol/server-filesystem", "."])],
34
- max_iterations=2,
34
+ max_iterations=5,
35
35
  )
36
36
 
37
37
  result = await agent.arun("What's the weather in Tokyo, and what's 12 + 30?")
@@ -55,6 +55,16 @@ async def main():
55
55
  result2 = await agent.arun("Say that last sum again, but doubled.")
56
56
  print(result2.output)
57
57
 
58
+ # Streaming (stream=True): tokens + tool events as they happen.
59
+ print("\n--- streaming ---")
60
+ async for event in await agent.arun("Weather in Delhi? Answer in one sentence.", stream=True):
61
+ if event.type == "text":
62
+ print(event.text, end="", flush=True)
63
+ elif event.type == "tool_call":
64
+ print(f"[calling {event.tool_call.name}({event.tool_call.arguments})]")
65
+ elif event.type == "done":
66
+ print("\nTokens:", event.result.usage)
67
+
58
68
 
59
69
  if __name__ == "__main__":
60
70
  asyncio.run(main())
@@ -1,34 +1,34 @@
1
- [build-system]
2
- requires = ["hatchling"]
3
- build-backend = "hatchling.build"
4
-
5
- [project]
6
- name = "agentropic"
7
- version = "0.2.2"
8
- description = "A minimal, hackable agentic framework: LLM calls via litellm, @tool-decorated functions, and MCP server support."
9
- readme = "README.md"
10
- requires-python = ">=3.9"
11
- license = { text = "MIT" }
12
- authors = [
13
- { name = "Vishal Tiwari", email = "vishaltiwari.up2019@gmail.com" }
14
- ]
15
- keywords = ["llm", "agent", "agents", "litellm", "mcp", "tools", "ai"]
16
- classifiers = [
17
- "Programming Language :: Python :: 3",
18
- "License :: OSI Approved :: MIT License",
19
- "Operating System :: OS Independent",
20
- "Development Status :: 3 - Alpha",
21
- "Intended Audience :: Developers",
22
- "Topic :: Software Development :: Libraries :: Python Modules",
23
- ]
24
- dependencies = [
25
- "litellm>=1.40.0",
26
- "pydantic>=2.0.0",
27
- ]
28
-
29
- [project.optional-dependencies]
30
- mcp = ["mcp>=1.0.0"]
31
- dev = ["pytest", "pytest-asyncio", "build", "twine"]
32
-
33
- [tool.hatch.build.targets.wheel]
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "agentropic"
7
+ version = "0.3.0"
8
+ description = "A minimal, hackable agentic framework: LLM calls via litellm, @tool-decorated functions, and MCP server support."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [
13
+ { name = "Vishal Tiwari", email = "vishaltiwari.up2019@gmail.com" }
14
+ ]
15
+ keywords = ["llm", "agent", "agents", "litellm", "mcp", "tools", "ai"]
16
+ classifiers = [
17
+ "Programming Language :: Python :: 3",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Operating System :: OS Independent",
20
+ "Development Status :: 3 - Alpha",
21
+ "Intended Audience :: Developers",
22
+ "Topic :: Software Development :: Libraries :: Python Modules",
23
+ ]
24
+ dependencies = [
25
+ "litellm>=1.40.0",
26
+ "pydantic>=2.0.0",
27
+ ]
28
+
29
+ [project.optional-dependencies]
30
+ mcp = ["mcp>=1.0.0"]
31
+ dev = ["pytest", "pytest-asyncio", "build", "twine"]
32
+
33
+ [tool.hatch.build.targets.wheel]
34
34
  packages = ["src/agentropic"]
@@ -1,27 +1,27 @@
1
- from .agent import Agent, AgentError, AgentRunResult, ToolCallRecord
2
- from .tools import tool, Tool, ToolRegistry
3
- from .llm import LLMClient, LLMResponse
4
- from .memory import Memory
5
- from .mcp.client import MCPConnection, StdioServer, SSEServer, MCPServerConfig
6
- from .tracing import AgentTracer, NullTracer
7
-
8
- __version__ = "0.2.0"
9
-
10
- __all__ = [
11
- "Agent",
12
- "AgentError",
13
- "AgentRunResult",
14
- "ToolCallRecord",
15
- "tool",
16
- "Tool",
17
- "ToolRegistry",
18
- "LLMClient",
19
- "LLMResponse",
20
- "Memory",
21
- "MCPConnection",
22
- "StdioServer",
23
- "SSEServer",
24
- "MCPServerConfig",
25
- "AgentTracer",
26
- "NullTracer",
1
+ from .agent import Agent, AgentError, AgentRunResult, StreamEvent, ToolCallRecord
2
+ from .tools import tool, Tool, ToolRegistry
3
+ from .llm import LLMClient, LLMResponse
4
+ from .memory import Memory
5
+ from .mcp.client import MCPConnection, MCPError, StdioServer, SSEServer, HTTPServer, MCPServerConfig
6
+
7
+ __version__ = "0.3.0"
8
+
9
+ __all__ = [
10
+ "Agent",
11
+ "AgentError",
12
+ "AgentRunResult",
13
+ "StreamEvent",
14
+ "ToolCallRecord",
15
+ "MCPError",
16
+ "HTTPServer",
17
+ "tool",
18
+ "Tool",
19
+ "ToolRegistry",
20
+ "LLMClient",
21
+ "LLMResponse",
22
+ "Memory",
23
+ "MCPConnection",
24
+ "StdioServer",
25
+ "SSEServer",
26
+ "MCPServerConfig",
27
27
  ]