feat(skills): add managed-agents knowledge skill
This commit is contained in:
parent
9b2012a3ba
commit
f3a3dcd997
2 changed files with 286 additions and 0 deletions
103
skills/managed-agents/SKILL.md
Normal file
103
skills/managed-agents/SKILL.md
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
---
|
||||||
|
name: managed-agents
|
||||||
|
description: |
|
||||||
|
This skill should be used when the user asks about "managed agents",
|
||||||
|
"Anthropic API agents", "cloud-hosted agents", "agent SDK",
|
||||||
|
"deploying agents to the cloud", "serverless agents",
|
||||||
|
"API-based agent deployment", "/v1/agents endpoint",
|
||||||
|
"remote agent hosting", "agent as a service"
|
||||||
|
version: 0.1.0
|
||||||
|
---
|
||||||
|
|
||||||
|
## What are managed agents
|
||||||
|
|
||||||
|
Managed agents are Anthropic-hosted agent runtimes accessed via the Agent SDK
|
||||||
|
(`@anthropic-ai/sdk` for TypeScript, `anthropic` for Python). Instead of running
|
||||||
|
Claude Code locally, the agent runs on Anthropic's infrastructure with persistent
|
||||||
|
sessions, tool access, and automatic scaling.
|
||||||
|
|
||||||
|
Key difference from local agents: managed agents don't have local filesystem
|
||||||
|
access by default. They work through tools you define in code, not through
|
||||||
|
Claude Code's built-in Read/Write/Bash tools.
|
||||||
|
|
||||||
|
## When to use managed agents vs local deployment
|
||||||
|
|
||||||
|
| Dimension | Managed Agents (API) | Local (Claude Code CLI) |
|
||||||
|
|-----------|---------------------|------------------------|
|
||||||
|
| Infrastructure | Anthropic-hosted | Your machine/server |
|
||||||
|
| Filesystem | Via tools you define | Full local access |
|
||||||
|
| MCP servers | Not available | Full MCP support |
|
||||||
|
| Scaling | Automatic | Manual |
|
||||||
|
| Cost model | Per-token API billing | Subscription or API key |
|
||||||
|
| Best for | SaaS products, API integrations | Personal pipelines, file-heavy work |
|
||||||
|
| Session persistence | Via API sessions | Via `--resume` / `--name` |
|
||||||
|
|
||||||
|
**Decision rule:** If your agents need local filesystem access, MCP servers, or
|
||||||
|
run as part of a personal workflow → use local deployment (cron/launchd/systemd/Docker).
|
||||||
|
If your agents are part of a product, need to scale, or don't need local files →
|
||||||
|
use managed agents.
|
||||||
|
|
||||||
|
**Important limitation:** Managed agents cannot use MCP servers. If your agent
|
||||||
|
system relies on MCP servers for Slack, GitHub, databases, or other integrations,
|
||||||
|
use local deployment with Docker for isolation instead.
|
||||||
|
|
||||||
|
## SDK patterns
|
||||||
|
|
||||||
|
For concrete code patterns, see:
|
||||||
|
`${CLAUDE_PLUGIN_ROOT}/skills/managed-agents/references/api-patterns.md`
|
||||||
|
|
||||||
|
## Session management
|
||||||
|
|
||||||
|
Managed agents support persistent sessions via the API:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Create a new session
|
||||||
|
const session = await client.agents.sessions.create({
|
||||||
|
agent_id: "ag_...",
|
||||||
|
system_prompt: "You are a research agent..."
|
||||||
|
});
|
||||||
|
|
||||||
|
// Resume an existing session
|
||||||
|
const response = await client.agents.sessions.messages.create({
|
||||||
|
agent_id: "ag_...",
|
||||||
|
session_id: session.id,
|
||||||
|
messages: [{ role: "user", content: "Continue the analysis" }]
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Sessions maintain conversation history and tool state across multiple
|
||||||
|
interactions, similar to `claude --resume` for local agents.
|
||||||
|
|
||||||
|
## Budget and cost considerations
|
||||||
|
|
||||||
|
Managed agents bill per token at standard API rates. For cost control:
|
||||||
|
|
||||||
|
1. **Set max_tokens** on each request to cap output length
|
||||||
|
2. **Use prompt caching** — cached input tokens cost 90% less
|
||||||
|
3. **Batch non-urgent work** — batch API gives 50% discount
|
||||||
|
4. **Monitor with Admin API** — if you have org access, use
|
||||||
|
`/v1/organizations/usage_report/messages` with an Admin API key
|
||||||
|
(`sk-ant-admin...`) for detailed cost breakdowns
|
||||||
|
5. **Use `--max-budget-usd`** flag for local headless runs as a budget cap
|
||||||
|
|
||||||
|
Note: The Usage & Cost API requires an Admin API key and organization account.
|
||||||
|
Individual accounts should estimate costs from token counts.
|
||||||
|
|
||||||
|
## Migration path: local → managed
|
||||||
|
|
||||||
|
1. Extract your agent's system prompt from `.claude/agents/[name].md`
|
||||||
|
2. Convert tool access to SDK tool definitions
|
||||||
|
3. Replace file-based memory with session persistence or external storage
|
||||||
|
4. Replace MCP server integrations with direct API calls in tool handlers
|
||||||
|
5. Test with the SDK before removing local deployment
|
||||||
|
|
||||||
|
This is a significant architectural change. Only migrate if you need API-based
|
||||||
|
access or auto-scaling. Local deployment is simpler and cheaper for personal use.
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
For a guided setup: run `/agent-factory:build` and choose "Managed Agents"
|
||||||
|
as the deployment target in Phase 6.
|
||||||
|
|
||||||
|
For manual setup: see the API patterns reference at
|
||||||
|
`${CLAUDE_PLUGIN_ROOT}/skills/managed-agents/references/api-patterns.md`
|
||||||
183
skills/managed-agents/references/api-patterns.md
Normal file
183
skills/managed-agents/references/api-patterns.md
Normal file
|
|
@ -0,0 +1,183 @@
|
||||||
|
# Managed Agents API Patterns
|
||||||
|
|
||||||
|
Code patterns for creating and managing agents via the Anthropic SDK.
|
||||||
|
All examples use `@anthropic-ai/sdk` (TypeScript) with Python equivalents noted.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Basic agent creation
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import Anthropic from "@anthropic-ai/sdk";
|
||||||
|
|
||||||
|
const client = new Anthropic();
|
||||||
|
|
||||||
|
// Create an agent with tools
|
||||||
|
const response = await client.messages.create({
|
||||||
|
model: "claude-sonnet-4-6",
|
||||||
|
max_tokens: 4096,
|
||||||
|
system: "You are a research agent. Produce structured briefs.",
|
||||||
|
tools: [
|
||||||
|
{
|
||||||
|
name: "web_search",
|
||||||
|
description: "Search the web for information",
|
||||||
|
input_schema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
query: { type: "string", description: "Search query" }
|
||||||
|
},
|
||||||
|
required: ["query"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
messages: [
|
||||||
|
{ role: "user", content: "Research the latest Claude Code features" }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Agent with persistent sessions
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Create a session-based agent
|
||||||
|
const session = await client.agents.sessions.create({
|
||||||
|
agent_id: "ag_your_agent_id",
|
||||||
|
system_prompt: `You are a data analyst. You have access to the
|
||||||
|
company database via the query tool. Always verify your findings
|
||||||
|
before reporting.`,
|
||||||
|
tools: [/* your tool definitions */]
|
||||||
|
});
|
||||||
|
|
||||||
|
// First interaction
|
||||||
|
const result1 = await client.agents.sessions.messages.create({
|
||||||
|
agent_id: "ag_your_agent_id",
|
||||||
|
session_id: session.id,
|
||||||
|
messages: [{ role: "user", content: "Analyze Q1 revenue trends" }]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Continue the conversation (session remembers context)
|
||||||
|
const result2 = await client.agents.sessions.messages.create({
|
||||||
|
agent_id: "ag_your_agent_id",
|
||||||
|
session_id: session.id,
|
||||||
|
messages: [{ role: "user", content: "Now compare with Q4 of last year" }]
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tool handling pattern
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
async function runAgentLoop(
|
||||||
|
client: Anthropic,
|
||||||
|
messages: Anthropic.MessageParam[],
|
||||||
|
tools: Anthropic.Tool[]
|
||||||
|
) {
|
||||||
|
let response = await client.messages.create({
|
||||||
|
model: "claude-sonnet-4-6",
|
||||||
|
max_tokens: 4096,
|
||||||
|
tools,
|
||||||
|
messages
|
||||||
|
});
|
||||||
|
|
||||||
|
while (response.stop_reason === "tool_use") {
|
||||||
|
const toolUseBlocks = response.content.filter(
|
||||||
|
(b): b is Anthropic.ToolUseBlock => b.type === "tool_use"
|
||||||
|
);
|
||||||
|
|
||||||
|
const toolResults: Anthropic.ToolResultBlockParam[] = [];
|
||||||
|
for (const toolUse of toolUseBlocks) {
|
||||||
|
const result = await executeToolCall(toolUse.name, toolUse.input);
|
||||||
|
toolResults.push({
|
||||||
|
type: "tool_result",
|
||||||
|
tool_use_id: toolUse.id,
|
||||||
|
content: JSON.stringify(result)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
messages.push({ role: "assistant", content: response.content });
|
||||||
|
messages.push({ role: "user", content: toolResults });
|
||||||
|
|
||||||
|
response = await client.messages.create({
|
||||||
|
model: "claude-sonnet-4-6",
|
||||||
|
max_tokens: 4096,
|
||||||
|
tools,
|
||||||
|
messages
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cost optimization with prompt caching
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const response = await client.messages.create({
|
||||||
|
model: "claude-sonnet-4-6",
|
||||||
|
max_tokens: 1024,
|
||||||
|
system: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
text: longSystemPrompt, // cached — 90% cheaper on reuse
|
||||||
|
cache_control: { type: "ephemeral" }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
messages: [{ role: "user", content: userQuery }]
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error handling
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
try {
|
||||||
|
const response = await client.messages.create(/* ... */);
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Anthropic.RateLimitError) {
|
||||||
|
// Retry with exponential backoff
|
||||||
|
await sleep(retryDelay);
|
||||||
|
retryDelay *= 2;
|
||||||
|
} else if (error instanceof Anthropic.APIError) {
|
||||||
|
console.error(`API error ${error.status}: ${error.message}`);
|
||||||
|
// Log for debugging, don't retry on 4xx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Python equivalent
|
||||||
|
|
||||||
|
```python
|
||||||
|
import anthropic
|
||||||
|
|
||||||
|
client = anthropic.Anthropic()
|
||||||
|
|
||||||
|
response = client.messages.create(
|
||||||
|
model="claude-sonnet-4-6",
|
||||||
|
max_tokens=4096,
|
||||||
|
system="You are a research agent.",
|
||||||
|
messages=[{"role": "user", "content": "Research topic X"}]
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deployment pattern: scheduled managed agent
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Run as a scheduled job (e.g., via cron or cloud scheduler)
|
||||||
|
async function dailyReport() {
|
||||||
|
const client = new Anthropic();
|
||||||
|
|
||||||
|
const response = await runAgentLoop(
|
||||||
|
client,
|
||||||
|
[{ role: "user", content: "Generate the daily status report" }],
|
||||||
|
reportTools
|
||||||
|
);
|
||||||
|
|
||||||
|
// Extract and save the report
|
||||||
|
const text = response.content
|
||||||
|
.filter((b): b is Anthropic.TextBlock => b.type === "text")
|
||||||
|
.map((b) => b.text)
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
await saveReport(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
dailyReport().catch(console.error);
|
||||||
|
```
|
||||||
Loading…
Add table
Add a link
Reference in a new issue