maestro-bundle 1.7.0 → 1.9.0

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.
@@ -0,0 +1,196 @@
1
+ ---
2
+ name: deep-agent-deployment
3
+ description: Deploy Deep Agents as APIs or CLI tools using FastAPI, LangGraph Platform, or Docker. Use when serving the agent as an API, deploying to production, or creating a CLI interface.
4
+ version: 1.0.0
5
+ author: Maestro
6
+ ---
7
+
8
+ # Deep Agent Deployment
9
+
10
+ Deploy your Deep Agent as a REST API, WebSocket server, or CLI tool for production use.
11
+
12
+ ## When to Use
13
+ - When serving the agent as an API endpoint
14
+ - When deploying to LangGraph Platform
15
+ - When creating a Docker container for the agent
16
+ - When building a CLI interface
17
+
18
+ ## Available Operations
19
+ 1. Serve as FastAPI REST API
20
+ 2. Add WebSocket streaming
21
+ 3. Deploy with Docker
22
+ 4. Deploy to LangGraph Platform
23
+ 5. Create CLI interface
24
+
25
+ ## Multi-Step Workflow
26
+
27
+ ### Step 1: FastAPI REST API
28
+
29
+ ```python
30
+ # api/server.py
31
+ from fastapi import FastAPI, HTTPException
32
+ from pydantic import BaseModel
33
+ from deepagents import create_deep_agent
34
+ from langgraph.checkpoint.postgres import PostgresSaver
35
+
36
+ app = FastAPI(title="Deep Agent API")
37
+
38
+ agent = create_deep_agent(
39
+ model="anthropic:claude-sonnet-4-6",
40
+ checkpointer=PostgresSaver(conn_string=os.environ["DATABASE_URL"])
41
+ )
42
+
43
+ class ChatRequest(BaseModel):
44
+ message: str
45
+ thread_id: str
46
+
47
+ class ChatResponse(BaseModel):
48
+ response: str
49
+ thread_id: str
50
+
51
+ @app.post("/api/chat", response_model=ChatResponse)
52
+ async def chat(req: ChatRequest):
53
+ config = {"configurable": {"thread_id": req.thread_id}}
54
+ result = agent.invoke(
55
+ {"messages": [{"role": "user", "content": req.message}]},
56
+ config=config
57
+ )
58
+ return ChatResponse(
59
+ response=result["messages"][-1].content,
60
+ thread_id=req.thread_id
61
+ )
62
+ ```
63
+
64
+ ### Step 2: WebSocket Streaming
65
+
66
+ ```python
67
+ # api/websocket.py
68
+ from fastapi import WebSocket
69
+
70
+ @app.websocket("/ws/chat/{thread_id}")
71
+ async def ws_chat(websocket: WebSocket, thread_id: str):
72
+ await websocket.accept()
73
+ config = {"configurable": {"thread_id": thread_id}}
74
+
75
+ while True:
76
+ message = await websocket.receive_text()
77
+
78
+ async for event in agent.astream_events(
79
+ {"messages": [{"role": "user", "content": message}]},
80
+ config=config,
81
+ version="v2"
82
+ ):
83
+ if event["event"] == "on_chat_model_stream":
84
+ chunk = event["data"]["chunk"].content
85
+ if chunk:
86
+ await websocket.send_text(chunk)
87
+
88
+ await websocket.send_text("[DONE]")
89
+ ```
90
+
91
+ ### Step 3: Docker
92
+
93
+ ```dockerfile
94
+ FROM python:3.11-slim
95
+ WORKDIR /app
96
+ COPY requirements.txt .
97
+ RUN pip install --no-cache-dir -r requirements.txt
98
+ COPY src/ ./src/
99
+ COPY skills/ ./skills/
100
+ USER 1000
101
+ EXPOSE 8000
102
+ CMD ["uvicorn", "src.api.server:app", "--host", "0.0.0.0", "--port", "8000"]
103
+ ```
104
+
105
+ ```bash
106
+ docker build -t deep-agent:latest .
107
+ docker run -p 8000:8000 -e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY deep-agent:latest
108
+ ```
109
+
110
+ ### Step 4: LangGraph Platform
111
+
112
+ ```python
113
+ # langgraph.json
114
+ {
115
+ "graphs": {
116
+ "agent": {
117
+ "path": "src/agent/main.py:agent"
118
+ }
119
+ },
120
+ "dependencies": ["deepagents", "langchain"]
121
+ }
122
+ ```
123
+
124
+ ```bash
125
+ # Deploy to LangGraph Platform
126
+ langgraph deploy
127
+ ```
128
+
129
+ ### Step 5: CLI Interface
130
+
131
+ ```python
132
+ # cli.py
133
+ import asyncio
134
+ from deepagents import create_deep_agent
135
+
136
+ async def main():
137
+ agent = create_deep_agent(model="anthropic:claude-sonnet-4-6")
138
+ config = {"configurable": {"thread_id": "cli-session"}}
139
+
140
+ print("Deep Agent CLI (type 'exit' to quit)")
141
+ while True:
142
+ user_input = input("\n> ")
143
+ if user_input.lower() == "exit":
144
+ break
145
+
146
+ async for event in agent.astream_events(
147
+ {"messages": [{"role": "user", "content": user_input}]},
148
+ config=config,
149
+ version="v2"
150
+ ):
151
+ if event["event"] == "on_chat_model_stream":
152
+ print(event["data"]["chunk"].content, end="", flush=True)
153
+
154
+ asyncio.run(main())
155
+ ```
156
+
157
+ ### Step 6: Verify
158
+
159
+ ```bash
160
+ # Test API
161
+ uvicorn src.api.server:app --reload --port 8000
162
+ curl -X POST http://localhost:8000/api/chat \
163
+ -H "Content-Type: application/json" \
164
+ -d '{"message": "Hello", "thread_id": "test-1"}'
165
+
166
+ # Test CLI
167
+ python cli.py
168
+ ```
169
+
170
+ ## Resources
171
+ - `references/deployment-checklist.md` — Production deployment checklist
172
+
173
+ ## Examples
174
+
175
+ ### Example 1: REST API
176
+ User asks: "Serve the agent as an API"
177
+ Response approach:
178
+ 1. Create FastAPI app with `/api/chat` endpoint
179
+ 2. Add PostgresSaver for persistence
180
+ 3. Run with `uvicorn`
181
+ 4. Test with curl
182
+
183
+ ### Example 2: Streaming UI
184
+ User asks: "Real-time streaming like ChatGPT"
185
+ Response approach:
186
+ 1. Add WebSocket endpoint
187
+ 2. Use `astream_events` for token-by-token streaming
188
+ 3. Send chunks via WebSocket
189
+ 4. Frontend connects and renders
190
+
191
+ ## Notes
192
+ - Always use PostgresSaver in production (not MemorySaver)
193
+ - Set resource limits in Docker (memory, CPU)
194
+ - Add health check endpoint: `GET /health`
195
+ - Rate limit the API endpoints
196
+ - Use environment variables for API keys, never hardcode
@@ -0,0 +1,152 @@
1
+ ---
2
+ name: deep-agent-hitl
3
+ description: Configure human-in-the-loop approval workflows for Deep Agents. Use when requiring human approval before destructive operations like file deletion, deployment, or email sending.
4
+ version: 1.0.0
5
+ author: Maestro
6
+ ---
7
+
8
+ # Deep Agent Human-in-the-Loop
9
+
10
+ Configure approval gates that pause the agent and wait for human approval before executing sensitive operations.
11
+
12
+ ## When to Use
13
+ - When the agent should ask before deleting files
14
+ - When deploys require human approval
15
+ - When sending emails/messages needs confirmation
16
+ - When any destructive operation needs a gate
17
+
18
+ ## Available Operations
19
+ 1. Configure `interrupt_on` per tool
20
+ 2. Handle approval/rejection flow
21
+ 3. Resume after approval
22
+ 4. Custom approval decisions
23
+
24
+ ## Multi-Step Workflow
25
+
26
+ ### Step 1: Configure Interrupts
27
+
28
+ ```python
29
+ from deepagents import create_deep_agent
30
+ from langgraph.checkpoint.memory import MemorySaver
31
+
32
+ agent = create_deep_agent(
33
+ model="anthropic:claude-sonnet-4-6",
34
+ tools=[delete_file, read_file, send_email, deploy],
35
+ interrupt_on={
36
+ "delete_file": True, # Always ask
37
+ "read_file": False, # Never ask
38
+ "send_email": True, # Always ask
39
+ "deploy": True, # Always ask
40
+ "write_file": { # Custom decisions
41
+ "allowed_decisions": ["approve", "reject", "modify"]
42
+ }
43
+ },
44
+ checkpointer=MemorySaver() # REQUIRED for interrupts
45
+ )
46
+ ```
47
+
48
+ ### Step 2: Run and Handle Interrupts
49
+
50
+ ```python
51
+ config = {"configurable": {"thread_id": "session-1"}}
52
+
53
+ # Agent runs until it hits an interrupt
54
+ result = agent.invoke(
55
+ {"messages": [{"role": "user", "content": "Delete the old log files"}]},
56
+ config=config
57
+ )
58
+
59
+ # Check if agent is waiting for approval
60
+ if result.get("__interrupt__"):
61
+ interrupt = result["__interrupt__"]
62
+ print(f"Agent wants to: {interrupt['tool']} with args: {interrupt['args']}")
63
+
64
+ # Approve
65
+ result = agent.invoke(
66
+ {"messages": [{"role": "user", "content": "approved"}]},
67
+ config=config
68
+ )
69
+
70
+ # Or reject
71
+ # result = agent.invoke(
72
+ # {"messages": [{"role": "user", "content": "rejected, don't delete those"}]},
73
+ # config=config
74
+ # )
75
+ ```
76
+
77
+ ### Step 3: Build Approval UI (FastAPI)
78
+
79
+ ```python
80
+ from fastapi import FastAPI
81
+ from pydantic import BaseModel
82
+
83
+ app = FastAPI()
84
+
85
+ class ApprovalRequest(BaseModel):
86
+ session_id: str
87
+ decision: str # "approve" or "reject"
88
+ reason: str = ""
89
+
90
+ @app.post("/api/approve")
91
+ async def approve(req: ApprovalRequest):
92
+ config = {"configurable": {"thread_id": req.session_id}}
93
+ result = agent.invoke(
94
+ {"messages": [{"role": "user", "content": req.decision}]},
95
+ config=config
96
+ )
97
+ return {"status": "resumed", "result": result["messages"][-1].content}
98
+ ```
99
+
100
+ ### Step 4: Verify
101
+
102
+ ```bash
103
+ python -c "
104
+ from deepagents import create_deep_agent
105
+ from langchain.tools import tool
106
+ from langgraph.checkpoint.memory import MemorySaver
107
+
108
+ @tool
109
+ def dangerous_operation(action: str) -> str:
110
+ '''Execute a dangerous operation.'''
111
+ return f'Executed: {action}'
112
+
113
+ agent = create_deep_agent(
114
+ tools=[dangerous_operation],
115
+ interrupt_on={'dangerous_operation': True},
116
+ checkpointer=MemorySaver()
117
+ )
118
+
119
+ config = {'configurable': {'thread_id': 'test-hitl'}}
120
+ result = agent.invoke(
121
+ {'messages': [{'role': 'user', 'content': 'Run dangerous operation: cleanup'}]},
122
+ config=config
123
+ )
124
+ print('Interrupted:', bool(result.get('__interrupt__')))
125
+ "
126
+ ```
127
+
128
+ ## Resources
129
+ - `references/hitl-patterns.md` — Human-in-the-loop patterns
130
+
131
+ ## Examples
132
+
133
+ ### Example 1: Approve Before Deploy
134
+ User asks: "Agent should ask before deploying"
135
+ Response approach:
136
+ 1. Add `"deploy": True` to `interrupt_on`
137
+ 2. Agent pauses before calling deploy tool
138
+ 3. Show user what will be deployed
139
+ 4. Resume on approval
140
+
141
+ ### Example 2: Custom Approval Decisions
142
+ User asks: "For file writes, allow approve, reject, or modify"
143
+ Response approach:
144
+ 1. Use `{"write_file": {"allowed_decisions": ["approve", "reject", "modify"]}}`
145
+ 2. If "modify", user provides updated content
146
+ 3. Agent retries with modified input
147
+
148
+ ## Notes
149
+ - `checkpointer` is REQUIRED — without it, interrupts don't work
150
+ - Agent remembers state during interrupt — it resumes exactly where it paused
151
+ - Use for: delete, deploy, send email, run destructive commands
152
+ - Don't interrupt on read-only operations (wastes user's time)
@@ -0,0 +1,158 @@
1
+ ---
2
+ name: deep-agent-memory
3
+ description: Configure persistent memory for Deep Agents using AGENTS.md and LangGraph Store. Use when the agent needs to remember context across sessions, persist learnings, or maintain long-term knowledge.
4
+ version: 1.0.0
5
+ author: Maestro
6
+ ---
7
+
8
+ # Deep Agent Memory
9
+
10
+ Give your Deep Agent persistent memory that survives across sessions using AGENTS.md files and LangGraph Store.
11
+
12
+ ## When to Use
13
+ - When the agent should remember context between sessions
14
+ - When loading project-specific knowledge at startup
15
+ - When persisting learnings across threads
16
+ - When configuring AGENTS.md for persistent context
17
+
18
+ ## Available Operations
19
+ 1. Load AGENTS.md as persistent context
20
+ 2. Configure LangGraph Store for cross-thread memory
21
+ 3. Use CompositeBackend for memory routing
22
+ 4. Persist agent learnings
23
+
24
+ ## Multi-Step Workflow
25
+
26
+ ### Step 1: AGENTS.md as Memory
27
+
28
+ ```python
29
+ from deepagents import create_deep_agent
30
+ from deepagents.backends.utils import create_file_data
31
+ from langgraph.checkpoint.memory import MemorySaver
32
+
33
+ agents_md = """
34
+ # Project Context
35
+
36
+ ## Architecture
37
+ This project uses Clean Architecture with Python FastAPI.
38
+
39
+ ## Conventions
40
+ - Use Pydantic for all DTOs
41
+ - Pytest for testing
42
+ - Ruff for linting
43
+ """
44
+
45
+ agent = create_deep_agent(
46
+ model="anthropic:claude-sonnet-4-6",
47
+ memory=["/AGENTS.md"],
48
+ checkpointer=MemorySaver()
49
+ )
50
+
51
+ result = agent.invoke(
52
+ {
53
+ "messages": [{"role": "user", "content": "What architecture do we use?"}],
54
+ "files": {"/AGENTS.md": create_file_data(agents_md)}
55
+ },
56
+ config={"configurable": {"thread_id": "session-1"}}
57
+ )
58
+ ```
59
+
60
+ ### Step 2: Persistent Store Memory
61
+
62
+ ```python
63
+ from deepagents import create_deep_agent
64
+ from deepagents.backends import StoreBackend
65
+ from langgraph.store.postgres import PostgresStore
66
+ from langgraph.checkpoint.postgres import PostgresSaver
67
+
68
+ # Production: PostgreSQL for both
69
+ store = PostgresStore(conn_string="postgresql://user:pass@localhost/agents")
70
+ checkpointer = PostgresSaver(conn_string="postgresql://user:pass@localhost/agents")
71
+
72
+ agent = create_deep_agent(
73
+ model="anthropic:claude-sonnet-4-6",
74
+ backend=lambda rt: StoreBackend(rt),
75
+ store=store,
76
+ checkpointer=checkpointer,
77
+ memory=["/AGENTS.md"]
78
+ )
79
+ ```
80
+
81
+ ### Step 3: CompositeBackend with Memory
82
+
83
+ ```python
84
+ from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
85
+
86
+ composite = lambda rt: CompositeBackend(
87
+ default=StateBackend(rt),
88
+ routes={
89
+ "/memories/": StoreBackend(rt), # Long-term memory: persistent
90
+ "/workspace/": StateBackend(rt), # Working files: ephemeral
91
+ }
92
+ )
93
+
94
+ agent = create_deep_agent(
95
+ backend=composite,
96
+ store=InMemoryStore()
97
+ )
98
+ # Agent writes to /memories/ for things it wants to remember
99
+ # Agent writes to /workspace/ for temporary work
100
+ ```
101
+
102
+ ### Step 4: Consistent Thread IDs
103
+
104
+ ```python
105
+ # Same thread_id = same conversation context
106
+ config = {"configurable": {"thread_id": f"project-{project_id}"}}
107
+
108
+ # First invocation
109
+ agent.invoke({"messages": [msg1]}, config=config)
110
+
111
+ # Later invocation — agent remembers the first one
112
+ agent.invoke({"messages": [msg2]}, config=config)
113
+ ```
114
+
115
+ ### Step 5: Verify
116
+
117
+ ```bash
118
+ python -c "
119
+ from deepagents import create_deep_agent
120
+ from langgraph.checkpoint.memory import MemorySaver
121
+
122
+ agent = create_deep_agent(checkpointer=MemorySaver())
123
+ config = {'configurable': {'thread_id': 'test-memory'}}
124
+
125
+ # First message
126
+ agent.invoke({'messages': [{'role': 'user', 'content': 'My name is João'}]}, config=config)
127
+
128
+ # Second message — should remember
129
+ result = agent.invoke({'messages': [{'role': 'user', 'content': 'What is my name?'}]}, config=config)
130
+ print(result['messages'][-1].content)
131
+ "
132
+ ```
133
+
134
+ ## Resources
135
+ - `references/memory-patterns.md` — Memory architecture patterns
136
+
137
+ ## Examples
138
+
139
+ ### Example 1: Project Context Memory
140
+ User asks: "Agent should know our project conventions"
141
+ Response approach:
142
+ 1. Write AGENTS.md with conventions
143
+ 2. Pass via `memory=["/AGENTS.md"]`
144
+ 3. Agent loads it every session
145
+
146
+ ### Example 2: Learning Memory
147
+ User asks: "Agent should remember what worked in previous sessions"
148
+ Response approach:
149
+ 1. Use CompositeBackend with StoreBackend for `/memories/`
150
+ 2. Agent writes learnings to `/memories/`
151
+ 3. Next session, agent reads from `/memories/`
152
+
153
+ ## Notes
154
+ - `checkpointer` is REQUIRED for memory to persist
155
+ - AGENTS.md follows the agents.md standard (https://agents.md/)
156
+ - Use PostgresStore for production, InMemoryStore for dev
157
+ - Thread ID determines conversation scope
158
+ - Memory files are loaded at session start
@@ -0,0 +1,131 @@
1
+ ---
2
+ name: deep-agent-middleware
3
+ description: Configure and create custom middleware for Deep Agents including logging, validation, and tool interception. Use when adding cross-cutting concerns, logging tool calls, or modifying agent behavior.
4
+ version: 1.0.0
5
+ author: Maestro
6
+ ---
7
+
8
+ # Deep Agent Middleware
9
+
10
+ Add cross-cutting concerns to Deep Agents with built-in and custom middleware for logging, validation, rate limiting, and tool interception.
11
+
12
+ ## When to Use
13
+ - When you need to log all tool calls
14
+ - When you need to validate inputs before tools execute
15
+ - When you need rate limiting on API calls
16
+ - When you need custom behavior around tool execution
17
+
18
+ ## Available Operations
19
+ 1. Use built-in middleware (TodoList, Filesystem, SubAgent, Summarization)
20
+ 2. Create custom middleware with `@wrap_tool_call`
21
+ 3. Chain multiple middleware
22
+ 4. Add conditional middleware
23
+
24
+ ## Multi-Step Workflow
25
+
26
+ ### Step 1: Understand Built-in Middleware
27
+
28
+ These are automatically active:
29
+
30
+ | Middleware | What it does | Can disable? |
31
+ |---|---|---|
32
+ | TodoListMiddleware | `write_todos` tool for planning | No |
33
+ | FilesystemMiddleware | `ls`, `read_file`, `write_file`, etc. | No |
34
+ | SubAgentMiddleware | `task` tool for delegation | No |
35
+ | SummarizationMiddleware | Compresses long conversations | No |
36
+ | AnthropicPromptCachingMiddleware | Token optimization for Anthropic | Auto |
37
+ | PatchToolCallsMiddleware | Repairs broken tool calls | Auto |
38
+
39
+ ### Step 2: Create Custom Middleware
40
+
41
+ ```python
42
+ # agent/middleware.py
43
+ from langchain.agents.middleware import wrap_tool_call
44
+ import time
45
+ import logging
46
+
47
+ logger = logging.getLogger(__name__)
48
+
49
+ @wrap_tool_call
50
+ def log_tool_calls(request, handler):
51
+ """Log every tool call with timing."""
52
+ start = time.time()
53
+ logger.info(f"[TOOL] {request.name} called with: {request.args}")
54
+
55
+ result = handler(request)
56
+
57
+ duration = time.time() - start
58
+ logger.info(f"[TOOL] {request.name} completed in {duration:.2f}s")
59
+ return result
60
+
61
+ @wrap_tool_call
62
+ def validate_file_paths(request, handler):
63
+ """Prevent access to sensitive files."""
64
+ if request.name in ("read_file", "write_file", "edit_file"):
65
+ path = request.args.get("path", "")
66
+ blocked = [".env", "secrets", "credentials", ".git/config"]
67
+ if any(b in path for b in blocked):
68
+ return f"Access denied: {path} is a protected file"
69
+
70
+ return handler(request)
71
+
72
+ @wrap_tool_call
73
+ def rate_limit_api_calls(request, handler):
74
+ """Rate limit external API calls."""
75
+ api_tools = ["internet_search", "call_api"]
76
+ if request.name in api_tools:
77
+ time.sleep(1) # Simple rate limit
78
+
79
+ return handler(request)
80
+ ```
81
+
82
+ ### Step 3: Register Middleware
83
+
84
+ ```python
85
+ from deepagents import create_deep_agent
86
+ from agent.middleware import log_tool_calls, validate_file_paths, rate_limit_api_calls
87
+
88
+ agent = create_deep_agent(
89
+ model="anthropic:claude-sonnet-4-6",
90
+ middleware=[
91
+ log_tool_calls,
92
+ validate_file_paths,
93
+ rate_limit_api_calls,
94
+ ]
95
+ )
96
+ ```
97
+
98
+ ### Step 4: Verify
99
+
100
+ ```bash
101
+ # Run agent and check logs
102
+ python agent/main.py 2>&1 | grep "[TOOL]"
103
+
104
+ # Run tests
105
+ pytest tests/test_middleware.py -v
106
+ ```
107
+
108
+ ## Resources
109
+ - `references/middleware-guide.md` — Middleware patterns and best practices
110
+
111
+ ## Examples
112
+
113
+ ### Example 1: Add Logging
114
+ User asks: "Log all tool calls with timing"
115
+ Response approach:
116
+ 1. Create `@wrap_tool_call` that logs name, args, duration
117
+ 2. Register in `create_deep_agent(middleware=[...])`
118
+ 3. Run agent, check logs
119
+
120
+ ### Example 2: Block Sensitive Files
121
+ User asks: "Agent should not read .env files"
122
+ Response approach:
123
+ 1. Create middleware that checks file paths
124
+ 2. Return "Access denied" for blocked paths
125
+ 3. Test with agent trying to read .env
126
+
127
+ ## Notes
128
+ - Do NOT mutate agent attributes after initialization — use graph state
129
+ - Middleware executes in order: first registered = outermost wrapper
130
+ - Built-in middleware cannot be removed
131
+ - Keep middleware lightweight — it runs on every tool call