Opinionated agent kit for building sophisticated ACP agents
Project description
chuk-acp-agent
Build powerful ACP agents with minimal boilerplate
A clean, type-safe framework for building editor agents. Features one-line MCP setup, direct result access, and zero legacy code.
# That's it - a complete working agent!
from chuk_acp_agent import Agent, Context
class MyAgent(Agent):
def __init__(self):
super().__init__()
self.add_mcp_server("echo", "uvx chuk-mcp-echo stdio") # One line!
async def on_prompt(self, ctx: Context, prompt: str):
result = await ctx.tools.call("echo_text", message=prompt)
yield f"Echo: {result.text}\n" # Direct access!
Features
- High-level abstractions: Rich
ContextAPI with memory, streaming, and tool integration - MCP integration: Built-in support for Model Context Protocol via
chuk-tool-processor- Simple config: One-line MCP server setup with
add_mcp_server() - Clean results: Direct
.textaccess, no manual extraction - Tool discovery: List available tools with
ctx.tools.list() - Batch execution: Parallel tool calls with
call_batch() - Load from file:
load_mcp_config("config.json")for file-based configuration
- Simple config: One-line MCP server setup with
- Session memory: Key-value storage scoped to session lifecycle
- Streaming responses: Async generator pattern with
yieldfor real-time output - Plan tracking: Create and update task plans with
send_plan()andupdate_plan() - Type-safe: Pydantic models throughout (AgentInfo, ToolResult, etc.)
Installation
pip install chuk-acp-agent
Quick Start
Minimal Agent
from chuk_acp_agent import Agent, Context
class MyAgent(Agent):
async def on_prompt(self, ctx: Context, prompt: str):
"""Handle user prompts - yield strings to stream back."""
# Increment message counter
count = ctx.memory.get("count", 0) + 1
ctx.memory.set("count", count)
yield f"Message #{count}\n"
yield f"You said: {prompt}\n"
yield f"Session: {ctx.session_id}\n"
if __name__ == "__main__":
MyAgent().run()
Run it:
# If installed in current environment
python my_agent.py
# Or use uv (recommended for development)
uv run my_agent.py
Test it with the chuk-acp client:
# Using uv (recommended)
uvx chuk-acp client uv run my_agent.py --prompt "Hello!"
# Or if chuk-acp-agent is installed globally
uvx chuk-acp client python my_agent.py --prompt "Hello!"
Using MCP Tools
Simple configuration and clean result access:
from chuk_acp_agent import Agent, Context
class MCPAgent(Agent):
def __init__(self):
super().__init__()
# Simple one-line configuration!
self.add_mcp_server("echo", "uvx chuk-mcp-echo stdio")
self.add_mcp_server("filesystem", "npx -y @modelcontextprotocol/server-filesystem /tmp")
async def on_prompt(self, ctx: Context, prompt: str):
# Call MCP tool - returns clean ToolResult
result = await ctx.tools.call("echo_text", message=prompt)
# Access text directly - no manual extraction!
yield f"Echo: {result.text}\n"
# List available tools
tools = await ctx.tools.list()
yield f"Available: {', '.join(t.name for t in tools)}\n"
# Batch execution (runs in parallel)
results = await ctx.tools.call_batch([
("echo_text", {"message": "First"}),
("echo_text", {"message": "Second"}),
])
for r in results:
yield f"- {r.text}\n"
Clean and simple - that's it!
Streaming & Progress
async def on_prompt(self, ctx: Context, prompt: str):
# Send plan
await ctx.send_plan([
{"content": "Analyzing code", "status": "in_progress"},
{"content": "Applying fixes", "status": "pending"},
])
# Stream tokens
yield "Analyzing...\n"
# Update plan
await ctx.update_plan(0, status="completed")
await ctx.update_plan(1, status="in_progress")
# Continue streaming
yield "Fixed 3 issues\n"
Context API
The Context object provides access to all agent capabilities:
Session Memory
# Store data per session
ctx.memory.set("current_file", "/path/to/file.py")
ctx.memory.set("user_preferences", {"theme": "dark"})
# Retrieve
file = ctx.memory.get("current_file")
prefs = ctx.memory.get("user_preferences", default={})
Tools (MCP)
# Call MCP tools - returns clean ToolResult
result = await ctx.tools.call("tool_name", **kwargs)
text = result.text # Direct text access
is_error = result.is_error # Check for errors
# List available tools (returns List[Tool])
tools = await ctx.tools.list()
for tool in tools:
print(f"{tool.name}: {tool.description}")
# Batch execution (parallel)
results = await ctx.tools.call_batch([
("echo_text", {"message": "one"}),
("echo_text", {"message": "two"}),
])
Streaming
# Stream text tokens
await ctx.emit("Processing...\n")
# Stream with flushing
async for token in llm_stream:
await ctx.emit(token)
Plans & Progress
# Create plan
await ctx.send_plan([
{"content": "Step 1", "status": "pending"},
{"content": "Step 2", "status": "pending"},
])
# Update plan
await ctx.update_plan(0, status="in_progress")
await ctx.update_plan(0, status="completed")
Agent Lifecycle
from chuk_acp import AgentInfo
from chuk_acp_agent import Agent, Context
class MyAgent(Agent):
def get_agent_info(self) -> AgentInfo:
"""Return agent metadata using Pydantic type."""
return AgentInfo(
name="my-agent",
version="1.0.0",
title="My Agent - Custom Agent",
)
async def on_new_session(self, ctx: Context) -> None:
"""Called when a new session starts."""
ctx.memory.set("session_start", time.time())
async def on_prompt(self, ctx: Context, prompt: str):
"""Handle user prompt. Yield strings to stream back."""
yield "Response\n"
async def on_cancel(self, ctx: Context) -> None:
"""Called when user cancels ongoing prompt."""
# Cleanup resources
pass
Middleware
Add cross-cutting behaviors:
from chuk_acp_agent import Agent, Context
from chuk_acp_agent.middlewares import TracingMiddleware, RateLimitMiddleware
class MyAgent(Agent):
def __init__(self):
super().__init__()
self.add_middleware(TracingMiddleware())
self.add_middleware(RateLimitMiddleware(max_tokens_per_minute=100000))
Editor Integration
Zed
Add to ~/.config/zed/settings.json:
{
"agent_servers": {
"My Agent": {
"command": "uv",
"args": ["run", "/absolute/path/to/my_agent.py"],
"env": {}
}
}
}
Or if chuk-acp-agent is installed globally:
{
"agent_servers": {
"My Agent": {
"command": "python",
"args": ["/absolute/path/to/my_agent.py"],
"env": {}
}
}
}
VS Code (future)
Coming soon.
Examples
See the examples/ directory for complete working examples:
Core Examples:
echo_agent.py- Minimal agent with session memoryfile_agent.py- File reading and analysisplan_agent.py- Task tracking with plans
MCP Integration:
mcp_agent_simple.py⭐ Recommended - Minimal MCP example (~20 lines)mcp_agent_advanced.py- Tool discovery, batch execution, error handlingmcp_agent.py- Full-featured multi-server setup
All examples showcase the clean DX improvements!
Architecture
chuk-acp-agent/
├─ agent/ # Core abstractions
│ ├─ base.py # Agent base class with add_mcp_server()
│ └─ context.py # Context with tools, memory, plans
├─ integrations/
│ └─ mcp_tools.py # MCP tool invoker (ToolResult, call_batch, list)
├─ models/
│ ├─ mcp.py # MCPConfig, MCPServerConfig (Pydantic)
│ ├─ tool.py # Tool, ToolParameter (Pydantic)
│ └─ tool_result.py # ToolResult wrapper
├─ exceptions.py # ToolNotFoundError, ToolExecutionError
└─ examples/ # Working example agents
Testing
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# With coverage
pytest --cov=chuk_acp_agent
Contributing
Contributions welcome! Please open an issue or PR.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file chuk_acp_agent-0.1.4.tar.gz.
File metadata
- Download URL: chuk_acp_agent-0.1.4.tar.gz
- Upload date:
- Size: 5.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4e60346d32bdb164b497ebda0c52e2b012cb534c8f207096064a574072e0d4b7
|
|
| MD5 |
65601a2ae45ef4f3de7a329ba3fdb831
|
|
| BLAKE2b-256 |
09b69d406b822587de56aac0dcd181aa5170f6f362aae3e82a549044d9e24237
|
File details
Details for the file chuk_acp_agent-0.1.4-py3-none-any.whl.
File metadata
- Download URL: chuk_acp_agent-0.1.4-py3-none-any.whl
- Upload date:
- Size: 5.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d780e471df6b0e1513a86adeb1ea09b913ef174932b9837d1994bb043aea0bc9
|
|
| MD5 |
b3b3bff689477d1dde6cc07b6534c453
|
|
| BLAKE2b-256 |
40adf46e21714dcf06eb2894a1fac6a96dc8d16ed7c5cf69346d76ceb93892cf
|