claudient 0.1.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.
- package/.claude-plugin/plugin.json +42 -0
- package/CONTEXT.md +58 -0
- package/README.md +165 -0
- package/agents/build-resolvers/de/python-resolver.md +64 -0
- package/agents/build-resolvers/de/typescript-resolver.md +65 -0
- package/agents/build-resolvers/es/python-resolver.md +64 -0
- package/agents/build-resolvers/es/typescript-resolver.md +65 -0
- package/agents/build-resolvers/fr/python-resolver.md +64 -0
- package/agents/build-resolvers/fr/typescript-resolver.md +65 -0
- package/agents/build-resolvers/nl/python-resolver.md +64 -0
- package/agents/build-resolvers/nl/typescript-resolver.md +65 -0
- package/agents/build-resolvers/python-resolver.md +62 -0
- package/agents/build-resolvers/typescript-resolver.md +63 -0
- package/agents/core/architect.md +64 -0
- package/agents/core/code-reviewer.md +78 -0
- package/agents/core/de/architect.md +66 -0
- package/agents/core/de/code-reviewer.md +80 -0
- package/agents/core/de/planner.md +63 -0
- package/agents/core/de/security-reviewer.md +93 -0
- package/agents/core/es/architect.md +66 -0
- package/agents/core/es/code-reviewer.md +80 -0
- package/agents/core/es/planner.md +63 -0
- package/agents/core/es/security-reviewer.md +93 -0
- package/agents/core/fr/architect.md +66 -0
- package/agents/core/fr/code-reviewer.md +80 -0
- package/agents/core/fr/planner.md +63 -0
- package/agents/core/fr/security-reviewer.md +93 -0
- package/agents/core/nl/architect.md +66 -0
- package/agents/core/nl/code-reviewer.md +80 -0
- package/agents/core/nl/planner.md +63 -0
- package/agents/core/nl/security-reviewer.md +93 -0
- package/agents/core/planner.md +61 -0
- package/agents/core/security-reviewer.md +91 -0
- package/guides/agent-orchestration.md +231 -0
- package/guides/de/agent-orchestration.md +174 -0
- package/guides/de/getting-started.md +164 -0
- package/guides/de/hooks-cookbook.md +160 -0
- package/guides/de/memory-management.md +153 -0
- package/guides/de/security.md +180 -0
- package/guides/de/skill-authoring.md +214 -0
- package/guides/de/token-optimization.md +156 -0
- package/guides/es/agent-orchestration.md +174 -0
- package/guides/es/getting-started.md +164 -0
- package/guides/es/hooks-cookbook.md +160 -0
- package/guides/es/memory-management.md +153 -0
- package/guides/es/security.md +180 -0
- package/guides/es/skill-authoring.md +214 -0
- package/guides/es/token-optimization.md +156 -0
- package/guides/fr/agent-orchestration.md +174 -0
- package/guides/fr/getting-started.md +164 -0
- package/guides/fr/hooks-cookbook.md +227 -0
- package/guides/fr/memory-management.md +169 -0
- package/guides/fr/security.md +180 -0
- package/guides/fr/skill-authoring.md +214 -0
- package/guides/fr/token-optimization.md +158 -0
- package/guides/getting-started.md +164 -0
- package/guides/hooks-cookbook.md +423 -0
- package/guides/memory-management.md +192 -0
- package/guides/nl/agent-orchestration.md +174 -0
- package/guides/nl/getting-started.md +164 -0
- package/guides/nl/hooks-cookbook.md +160 -0
- package/guides/nl/memory-management.md +153 -0
- package/guides/nl/security.md +180 -0
- package/guides/nl/skill-authoring.md +214 -0
- package/guides/nl/token-optimization.md +156 -0
- package/guides/security.md +229 -0
- package/guides/skill-authoring.md +226 -0
- package/guides/token-optimization.md +169 -0
- package/hooks/lifecycle/cost-tracker.md +49 -0
- package/hooks/lifecycle/cost-tracker.sh +59 -0
- package/hooks/lifecycle/pre-compact-save.md +56 -0
- package/hooks/lifecycle/pre-compact-save.sh +37 -0
- package/hooks/lifecycle/session-start.md +50 -0
- package/hooks/lifecycle/session-start.sh +47 -0
- package/hooks/post-tool-use/audit-log.md +53 -0
- package/hooks/post-tool-use/audit-log.sh +53 -0
- package/hooks/post-tool-use/prettier.md +53 -0
- package/hooks/post-tool-use/prettier.sh +49 -0
- package/hooks/pre-tool-use/block-dangerous.md +48 -0
- package/hooks/pre-tool-use/block-dangerous.sh +76 -0
- package/hooks/pre-tool-use/git-push-confirm.md +46 -0
- package/hooks/pre-tool-use/git-push-confirm.sh +36 -0
- package/mcp/configs/github.json +11 -0
- package/mcp/configs/postgres.json +11 -0
- package/mcp/de/recommended-servers.md +170 -0
- package/mcp/es/recommended-servers.md +170 -0
- package/mcp/fr/recommended-servers.md +170 -0
- package/mcp/nl/recommended-servers.md +170 -0
- package/mcp/recommended-servers.md +168 -0
- package/package.json +45 -0
- package/prompts/project-starters/de/fastapi-project.md +62 -0
- package/prompts/project-starters/de/nextjs-project.md +82 -0
- package/prompts/project-starters/es/fastapi-project.md +62 -0
- package/prompts/project-starters/es/nextjs-project.md +82 -0
- package/prompts/project-starters/fastapi-project.md +60 -0
- package/prompts/project-starters/fr/fastapi-project.md +62 -0
- package/prompts/project-starters/fr/nextjs-project.md +82 -0
- package/prompts/project-starters/nextjs-project.md +80 -0
- package/prompts/project-starters/nl/fastapi-project.md +62 -0
- package/prompts/project-starters/nl/nextjs-project.md +82 -0
- package/prompts/system-prompts/ai-product.md +80 -0
- package/prompts/system-prompts/data-pipeline.md +76 -0
- package/prompts/system-prompts/de/ai-product.md +82 -0
- package/prompts/system-prompts/de/data-pipeline.md +78 -0
- package/prompts/system-prompts/de/saas-backend.md +71 -0
- package/prompts/system-prompts/es/ai-product.md +82 -0
- package/prompts/system-prompts/es/data-pipeline.md +78 -0
- package/prompts/system-prompts/es/saas-backend.md +71 -0
- package/prompts/system-prompts/fr/ai-product.md +82 -0
- package/prompts/system-prompts/fr/data-pipeline.md +78 -0
- package/prompts/system-prompts/fr/saas-backend.md +71 -0
- package/prompts/system-prompts/nl/ai-product.md +82 -0
- package/prompts/system-prompts/nl/data-pipeline.md +78 -0
- package/prompts/system-prompts/nl/saas-backend.md +71 -0
- package/prompts/system-prompts/saas-backend.md +69 -0
- package/prompts/task-specific/changelog.md +81 -0
- package/prompts/task-specific/de/changelog.md +83 -0
- package/prompts/task-specific/de/debugging.md +78 -0
- package/prompts/task-specific/de/pr-description.md +69 -0
- package/prompts/task-specific/debugging.md +76 -0
- package/prompts/task-specific/es/changelog.md +83 -0
- package/prompts/task-specific/es/debugging.md +78 -0
- package/prompts/task-specific/es/pr-description.md +69 -0
- package/prompts/task-specific/fr/changelog.md +83 -0
- package/prompts/task-specific/fr/debugging.md +78 -0
- package/prompts/task-specific/fr/pr-description.md +69 -0
- package/prompts/task-specific/nl/changelog.md +83 -0
- package/prompts/task-specific/nl/debugging.md +78 -0
- package/prompts/task-specific/nl/pr-description.md +69 -0
- package/prompts/task-specific/pr-description.md +67 -0
- package/rules/common/coding-style.md +45 -0
- package/rules/common/de/coding-style.md +47 -0
- package/rules/common/de/git.md +48 -0
- package/rules/common/de/performance.md +40 -0
- package/rules/common/de/security.md +45 -0
- package/rules/common/de/testing.md +45 -0
- package/rules/common/es/coding-style.md +47 -0
- package/rules/common/es/git.md +48 -0
- package/rules/common/es/performance.md +40 -0
- package/rules/common/es/security.md +45 -0
- package/rules/common/es/testing.md +45 -0
- package/rules/common/fr/coding-style.md +47 -0
- package/rules/common/fr/git.md +48 -0
- package/rules/common/fr/performance.md +40 -0
- package/rules/common/fr/security.md +45 -0
- package/rules/common/fr/testing.md +45 -0
- package/rules/common/git.md +46 -0
- package/rules/common/nl/coding-style.md +47 -0
- package/rules/common/nl/git.md +48 -0
- package/rules/common/nl/performance.md +40 -0
- package/rules/common/nl/security.md +45 -0
- package/rules/common/nl/testing.md +45 -0
- package/rules/common/performance.md +38 -0
- package/rules/common/security.md +43 -0
- package/rules/common/testing.md +43 -0
- package/rules/language-specific/de/go.md +48 -0
- package/rules/language-specific/de/python.md +38 -0
- package/rules/language-specific/de/typescript.md +51 -0
- package/rules/language-specific/es/go.md +48 -0
- package/rules/language-specific/es/python.md +38 -0
- package/rules/language-specific/es/typescript.md +51 -0
- package/rules/language-specific/fr/go.md +48 -0
- package/rules/language-specific/fr/python.md +38 -0
- package/rules/language-specific/fr/typescript.md +51 -0
- package/rules/language-specific/go.md +46 -0
- package/rules/language-specific/nl/go.md +48 -0
- package/rules/language-specific/nl/python.md +38 -0
- package/rules/language-specific/nl/typescript.md +51 -0
- package/rules/language-specific/python.md +36 -0
- package/rules/language-specific/typescript.md +49 -0
- package/scripts/cli.js +161 -0
- package/scripts/link-skills.sh +35 -0
- package/scripts/list-skills.sh +34 -0
- package/skills/ai-engineering/agent-construction.md +285 -0
- package/skills/ai-engineering/claude-api.md +248 -0
- package/skills/ai-engineering/de/agent-construction.md +287 -0
- package/skills/ai-engineering/de/claude-api.md +250 -0
- package/skills/ai-engineering/es/agent-construction.md +287 -0
- package/skills/ai-engineering/es/claude-api.md +250 -0
- package/skills/ai-engineering/fr/agent-construction.md +287 -0
- package/skills/ai-engineering/fr/claude-api.md +250 -0
- package/skills/ai-engineering/nl/agent-construction.md +287 -0
- package/skills/ai-engineering/nl/claude-api.md +250 -0
- package/skills/backend/dotnet/csharp.md +304 -0
- package/skills/backend/dotnet/de/csharp.md +306 -0
- package/skills/backend/dotnet/es/csharp.md +306 -0
- package/skills/backend/dotnet/fr/csharp.md +306 -0
- package/skills/backend/dotnet/nl/csharp.md +306 -0
- package/skills/backend/go/de/go.md +307 -0
- package/skills/backend/go/es/go.md +307 -0
- package/skills/backend/go/fr/go.md +307 -0
- package/skills/backend/go/go.md +305 -0
- package/skills/backend/go/nl/go.md +307 -0
- package/skills/backend/nodejs/de/nestjs.md +274 -0
- package/skills/backend/nodejs/de/nextjs.md +222 -0
- package/skills/backend/nodejs/es/nestjs.md +274 -0
- package/skills/backend/nodejs/es/nextjs.md +222 -0
- package/skills/backend/nodejs/fr/nestjs.md +274 -0
- package/skills/backend/nodejs/fr/nextjs.md +222 -0
- package/skills/backend/nodejs/nestjs.md +272 -0
- package/skills/backend/nodejs/nextjs.md +220 -0
- package/skills/backend/nodejs/nl/nestjs.md +274 -0
- package/skills/backend/nodejs/nl/nextjs.md +222 -0
- package/skills/backend/python/de/django.md +285 -0
- package/skills/backend/python/de/fastapi.md +244 -0
- package/skills/backend/python/django.md +283 -0
- package/skills/backend/python/es/django.md +285 -0
- package/skills/backend/python/es/fastapi.md +244 -0
- package/skills/backend/python/fastapi.md +242 -0
- package/skills/backend/python/fr/django.md +285 -0
- package/skills/backend/python/fr/fastapi.md +244 -0
- package/skills/backend/python/nl/django.md +285 -0
- package/skills/backend/python/nl/fastapi.md +244 -0
- package/skills/data-ml/dbt-data-pipelines.md +155 -0
- package/skills/data-ml/de/dbt-data-pipelines.md +157 -0
- package/skills/data-ml/de/pandas-polars.md +147 -0
- package/skills/data-ml/de/pytorch-tensorflow.md +171 -0
- package/skills/data-ml/es/dbt-data-pipelines.md +157 -0
- package/skills/data-ml/es/pandas-polars.md +147 -0
- package/skills/data-ml/es/pytorch-tensorflow.md +171 -0
- package/skills/data-ml/fr/dbt-data-pipelines.md +157 -0
- package/skills/data-ml/fr/pandas-polars.md +147 -0
- package/skills/data-ml/fr/pytorch-tensorflow.md +171 -0
- package/skills/data-ml/nl/dbt-data-pipelines.md +157 -0
- package/skills/data-ml/nl/pandas-polars.md +147 -0
- package/skills/data-ml/nl/pytorch-tensorflow.md +171 -0
- package/skills/data-ml/pandas-polars.md +145 -0
- package/skills/data-ml/pytorch-tensorflow.md +169 -0
- package/skills/database/de/graphql.md +181 -0
- package/skills/database/es/graphql.md +181 -0
- package/skills/database/fr/graphql.md +181 -0
- package/skills/database/graphql.md +179 -0
- package/skills/database/nl/graphql.md +181 -0
- package/skills/devops-infra/de/docker.md +133 -0
- package/skills/devops-infra/de/github-actions.md +179 -0
- package/skills/devops-infra/de/kubernetes.md +129 -0
- package/skills/devops-infra/de/terraform.md +130 -0
- package/skills/devops-infra/docker.md +131 -0
- package/skills/devops-infra/es/docker.md +133 -0
- package/skills/devops-infra/es/github-actions.md +179 -0
- package/skills/devops-infra/es/kubernetes.md +129 -0
- package/skills/devops-infra/es/terraform.md +130 -0
- package/skills/devops-infra/fr/docker.md +133 -0
- package/skills/devops-infra/fr/github-actions.md +179 -0
- package/skills/devops-infra/fr/kubernetes.md +129 -0
- package/skills/devops-infra/fr/terraform.md +130 -0
- package/skills/devops-infra/github-actions.md +177 -0
- package/skills/devops-infra/kubernetes.md +127 -0
- package/skills/devops-infra/nl/docker.md +133 -0
- package/skills/devops-infra/nl/github-actions.md +179 -0
- package/skills/devops-infra/nl/kubernetes.md +129 -0
- package/skills/devops-infra/nl/terraform.md +130 -0
- package/skills/devops-infra/terraform.md +128 -0
- package/skills/finance-payments/de/stripe.md +187 -0
- package/skills/finance-payments/es/stripe.md +187 -0
- package/skills/finance-payments/fr/stripe.md +187 -0
- package/skills/finance-payments/nl/stripe.md +187 -0
- package/skills/finance-payments/stripe.md +185 -0
- package/workflows/code-review.md +151 -0
- package/workflows/de/code-review.md +153 -0
- package/workflows/de/debugging-session.md +146 -0
- package/workflows/de/feature-development.md +155 -0
- package/workflows/de/new-project-bootstrap.md +175 -0
- package/workflows/de/refactor-safely.md +150 -0
- package/workflows/debugging-session.md +144 -0
- package/workflows/es/code-review.md +153 -0
- package/workflows/es/debugging-session.md +146 -0
- package/workflows/es/feature-development.md +155 -0
- package/workflows/es/new-project-bootstrap.md +175 -0
- package/workflows/es/refactor-safely.md +150 -0
- package/workflows/feature-development.md +153 -0
- package/workflows/fr/code-review.md +153 -0
- package/workflows/fr/debugging-session.md +146 -0
- package/workflows/fr/feature-development.md +155 -0
- package/workflows/fr/new-project-bootstrap.md +175 -0
- package/workflows/fr/refactor-safely.md +150 -0
- package/workflows/new-project-bootstrap.md +173 -0
- package/workflows/nl/code-review.md +153 -0
- package/workflows/nl/debugging-session.md +146 -0
- package/workflows/nl/feature-development.md +155 -0
- package/workflows/nl/new-project-bootstrap.md +175 -0
- package/workflows/nl/refactor-safely.md +150 -0
- package/workflows/refactor-safely.md +148 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# Claude API Skill
|
|
2
|
+
|
|
3
|
+
## When to activate
|
|
4
|
+
- Writing code that calls the Anthropic Claude API (Python or TypeScript SDK)
|
|
5
|
+
- Implementing prompt caching, streaming, or batch processing
|
|
6
|
+
- Designing multi-turn conversation management
|
|
7
|
+
- Selecting the right Claude model (Haiku, Sonnet, Opus) for a task
|
|
8
|
+
- Adding tool use / function calling to a Claude integration
|
|
9
|
+
- Optimizing for cost or latency in a production Claude app
|
|
10
|
+
|
|
11
|
+
## When NOT to use
|
|
12
|
+
- OpenAI or other provider APIs — different SDK, different patterns
|
|
13
|
+
- Generic LLM advice unrelated to the Anthropic API
|
|
14
|
+
- Projects already using LangChain or LlamaIndex abstractions — address the abstraction layer instead
|
|
15
|
+
|
|
16
|
+
## Instructions
|
|
17
|
+
|
|
18
|
+
### Model selection guide
|
|
19
|
+
| Model | Use when | Avoid when |
|
|
20
|
+
|-------|----------|------------|
|
|
21
|
+
| `claude-haiku-4-5-20251001` | Classification, extraction, routing, simple Q&A, high-volume low-cost | Complex reasoning, multi-step code generation |
|
|
22
|
+
| `claude-sonnet-4-6` | General-purpose: code, analysis, writing, agentic workflows | Token-constrained budgets at massive scale |
|
|
23
|
+
| `claude-opus-4-7` | Expert-level reasoning, nuanced judgment, complex long-form | Most tasks — usually Sonnet is sufficient |
|
|
24
|
+
|
|
25
|
+
### Basic message call (Python)
|
|
26
|
+
```python
|
|
27
|
+
import anthropic
|
|
28
|
+
|
|
29
|
+
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY from env
|
|
30
|
+
|
|
31
|
+
message = client.messages.create(
|
|
32
|
+
model="claude-sonnet-4-6",
|
|
33
|
+
max_tokens=1024,
|
|
34
|
+
system="You are a helpful assistant specialized in Python.",
|
|
35
|
+
messages=[
|
|
36
|
+
{"role": "user", "content": "Explain Python's GIL in 3 sentences."}
|
|
37
|
+
]
|
|
38
|
+
)
|
|
39
|
+
print(message.content[0].text)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Prompt caching (critical for cost)
|
|
43
|
+
Prompt caching can reduce costs by up to 90% for repeated context. Cache stable content (system prompts, large documents, few-shot examples).
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
message = client.messages.create(
|
|
47
|
+
model="claude-sonnet-4-6",
|
|
48
|
+
max_tokens=1024,
|
|
49
|
+
system=[
|
|
50
|
+
{
|
|
51
|
+
"type": "text",
|
|
52
|
+
"text": "You are a code review assistant. Here are our coding standards: ...",
|
|
53
|
+
"cache_control": {"type": "ephemeral"} # Cache this block
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
messages=[
|
|
57
|
+
{
|
|
58
|
+
"role": "user",
|
|
59
|
+
"content": [
|
|
60
|
+
{
|
|
61
|
+
"type": "text",
|
|
62
|
+
"text": large_document,
|
|
63
|
+
"cache_control": {"type": "ephemeral"} # Also cache the document
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"type": "text",
|
|
67
|
+
"text": "Summarize the key points."
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
)
|
|
73
|
+
# Check cache usage in response
|
|
74
|
+
print(message.usage.cache_read_input_tokens) # tokens read from cache
|
|
75
|
+
print(message.usage.cache_creation_input_tokens) # tokens written to cache
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Cache rules:
|
|
79
|
+
- Minimum cacheable block: 1024 tokens (Sonnet/Opus), 2048 tokens (Haiku)
|
|
80
|
+
- Cache TTL: 5 minutes
|
|
81
|
+
- Only the last `cache_control` block in a message array matters — cache points are cumulative
|
|
82
|
+
|
|
83
|
+
### Streaming
|
|
84
|
+
```python
|
|
85
|
+
with client.messages.stream(
|
|
86
|
+
model="claude-sonnet-4-6",
|
|
87
|
+
max_tokens=1024,
|
|
88
|
+
messages=[{"role": "user", "content": prompt}]
|
|
89
|
+
) as stream:
|
|
90
|
+
for text in stream.text_stream:
|
|
91
|
+
print(text, end="", flush=True)
|
|
92
|
+
|
|
93
|
+
# Or with events:
|
|
94
|
+
with client.messages.stream(...) as stream:
|
|
95
|
+
for event in stream:
|
|
96
|
+
if event.type == "content_block_delta":
|
|
97
|
+
print(event.delta.text, end="")
|
|
98
|
+
elif event.type == "message_stop":
|
|
99
|
+
print() # newline when done
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Tool use
|
|
103
|
+
```python
|
|
104
|
+
tools = [
|
|
105
|
+
{
|
|
106
|
+
"name": "get_weather",
|
|
107
|
+
"description": "Get current weather for a city",
|
|
108
|
+
"input_schema": {
|
|
109
|
+
"type": "object",
|
|
110
|
+
"properties": {
|
|
111
|
+
"city": {"type": "string", "description": "City name"},
|
|
112
|
+
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
|
|
113
|
+
},
|
|
114
|
+
"required": ["city"]
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
response = client.messages.create(
|
|
120
|
+
model="claude-sonnet-4-6",
|
|
121
|
+
max_tokens=1024,
|
|
122
|
+
tools=tools,
|
|
123
|
+
messages=[{"role": "user", "content": "What's the weather in Paris?"}]
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Check if Claude wants to use a tool
|
|
127
|
+
if response.stop_reason == "tool_use":
|
|
128
|
+
tool_use = next(b for b in response.content if b.type == "tool_use")
|
|
129
|
+
tool_result = call_tool(tool_use.name, tool_use.input)
|
|
130
|
+
|
|
131
|
+
# Continue conversation with tool result
|
|
132
|
+
follow_up = client.messages.create(
|
|
133
|
+
model="claude-sonnet-4-6",
|
|
134
|
+
max_tokens=1024,
|
|
135
|
+
tools=tools,
|
|
136
|
+
messages=[
|
|
137
|
+
{"role": "user", "content": "What's the weather in Paris?"},
|
|
138
|
+
{"role": "assistant", "content": response.content},
|
|
139
|
+
{
|
|
140
|
+
"role": "user",
|
|
141
|
+
"content": [{
|
|
142
|
+
"type": "tool_result",
|
|
143
|
+
"tool_use_id": tool_use.id,
|
|
144
|
+
"content": json.dumps(tool_result)
|
|
145
|
+
}]
|
|
146
|
+
}
|
|
147
|
+
]
|
|
148
|
+
)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Multi-turn conversation
|
|
152
|
+
```python
|
|
153
|
+
class Conversation:
|
|
154
|
+
def __init__(self, system: str, model: str = "claude-sonnet-4-6"):
|
|
155
|
+
self.client = anthropic.Anthropic()
|
|
156
|
+
self.model = model
|
|
157
|
+
self.system = system
|
|
158
|
+
self.messages: list[dict] = []
|
|
159
|
+
|
|
160
|
+
def chat(self, user_message: str, max_tokens: int = 1024) -> str:
|
|
161
|
+
self.messages.append({"role": "user", "content": user_message})
|
|
162
|
+
response = self.client.messages.create(
|
|
163
|
+
model=self.model,
|
|
164
|
+
max_tokens=max_tokens,
|
|
165
|
+
system=self.system,
|
|
166
|
+
messages=self.messages,
|
|
167
|
+
)
|
|
168
|
+
assistant_message = response.content[0].text
|
|
169
|
+
self.messages.append({"role": "assistant", "content": assistant_message})
|
|
170
|
+
return assistant_message
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Batch processing
|
|
174
|
+
```python
|
|
175
|
+
from anthropic.types.message_create_params import MessageCreateParamsNonStreaming
|
|
176
|
+
from anthropic.types.messages.batch_create_params import Request
|
|
177
|
+
|
|
178
|
+
requests = [
|
|
179
|
+
Request(
|
|
180
|
+
custom_id=f"review-{i}",
|
|
181
|
+
params=MessageCreateParamsNonStreaming(
|
|
182
|
+
model="claude-haiku-4-5-20251001",
|
|
183
|
+
max_tokens=256,
|
|
184
|
+
messages=[{"role": "user", "content": f"Classify: {review}"}],
|
|
185
|
+
)
|
|
186
|
+
)
|
|
187
|
+
for i, review in enumerate(reviews)
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
batch = client.messages.batches.create(requests=requests)
|
|
191
|
+
print(f"Batch ID: {batch.id}")
|
|
192
|
+
|
|
193
|
+
# Poll for results (or use webhooks)
|
|
194
|
+
import time
|
|
195
|
+
while True:
|
|
196
|
+
batch = client.messages.batches.retrieve(batch.id)
|
|
197
|
+
if batch.processing_status == "ended":
|
|
198
|
+
break
|
|
199
|
+
time.sleep(60)
|
|
200
|
+
|
|
201
|
+
for result in client.messages.batches.results(batch.id):
|
|
202
|
+
print(result.custom_id, result.result.message.content[0].text)
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Error handling and retries
|
|
206
|
+
```python
|
|
207
|
+
from anthropic import APIStatusError, APITimeoutError, RateLimitError
|
|
208
|
+
|
|
209
|
+
def call_with_retry(client, **kwargs, max_retries=3):
|
|
210
|
+
for attempt in range(max_retries):
|
|
211
|
+
try:
|
|
212
|
+
return client.messages.create(**kwargs)
|
|
213
|
+
except RateLimitError:
|
|
214
|
+
wait = 2 ** attempt
|
|
215
|
+
time.sleep(wait)
|
|
216
|
+
except APITimeoutError:
|
|
217
|
+
if attempt == max_retries - 1:
|
|
218
|
+
raise
|
|
219
|
+
time.sleep(1)
|
|
220
|
+
except APIStatusError as e:
|
|
221
|
+
if e.status_code >= 500 and attempt < max_retries - 1:
|
|
222
|
+
time.sleep(2 ** attempt)
|
|
223
|
+
else:
|
|
224
|
+
raise
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Cost optimization checklist
|
|
228
|
+
- Use Haiku for classification, routing, and simple extraction tasks
|
|
229
|
+
- Enable prompt caching for any system prompt > 1024 tokens
|
|
230
|
+
- Use batch API for offline/async workloads — 50% cost reduction
|
|
231
|
+
- Set `max_tokens` to the minimum needed — you pay for output tokens generated
|
|
232
|
+
- Cache large documents in the user message, not just the system prompt
|
|
233
|
+
- Monitor `cache_read_input_tokens` vs `input_tokens` ratio — target >80% for stable contexts
|
|
234
|
+
|
|
235
|
+
## Example
|
|
236
|
+
|
|
237
|
+
**User:** Build a Python class that classifies customer support tickets into categories using Claude, with prompt caching for the category list and streaming for the explanation.
|
|
238
|
+
|
|
239
|
+
**Expected output:**
|
|
240
|
+
- `TicketClassifier` class with `ANTHROPIC_API_KEY` from env
|
|
241
|
+
- System prompt with all categories cached via `cache_control: ephemeral`
|
|
242
|
+
- `classify(ticket_text)` → returns `{category: str, confidence: str}` parsed from structured output
|
|
243
|
+
- `classify_and_explain(ticket_text)` → streams the explanation to stdout
|
|
244
|
+
- Uses `claude-haiku-4-5-20251001` for classification (cost-efficient), `claude-sonnet-4-6` for explanation
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
> **Work with us:** Claudient is backed by [Uitbreiden](https://uitbreiden.com/) — we build AI products and B2B solutions with developer communities. [uitbreiden.com](https://uitbreiden.com/)
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
> 🇩🇪 Dies ist die deutsche Übersetzung. [Englische Version](../agent-construction.md).
|
|
2
|
+
|
|
3
|
+
# Agent Construction Skill
|
|
4
|
+
|
|
5
|
+
## Wann aktivieren
|
|
6
|
+
- Ein Multi-Agent-System mit Claude entwerfen (Orchestrator + Subagenten)
|
|
7
|
+
- Einen Claude-gestützten Agenten bauen, der Tools über mehrere Turns verwendet
|
|
8
|
+
- Speicher für einen langlebigen Agenten entwerfen (In-Kontext vs. extern)
|
|
9
|
+
- Agentenfehler, Wiederholungen und Abbruchbedingungen behandeln
|
|
10
|
+
- Agenten-Handoffs zwischen spezialisierten Subagenten implementieren
|
|
11
|
+
|
|
12
|
+
## Wann NICHT verwenden
|
|
13
|
+
- Einzelne Claude API-Aufrufe — der Claude API Skill reicht aus
|
|
14
|
+
- Einfache Chatbots ohne Tool Use oder autonome Entscheidungsfindung
|
|
15
|
+
- LangChain/LlamaIndex-Abstraktionen — die Abstraktionsebene direkt ansprechen
|
|
16
|
+
|
|
17
|
+
## Anweisungen
|
|
18
|
+
|
|
19
|
+
### Agenten-Architekturmuster
|
|
20
|
+
|
|
21
|
+
**Einzelner Agent mit Tools** — eine Claude-Instanz, mehrere Tools, Schleife bis Aufgabe erledigt:
|
|
22
|
+
```
|
|
23
|
+
User → Agent → [Tool A] → [Tool B] → Agent → User
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Orchestrator + Subagenten** — ein Elternteil spawnt spezialisierte Kinder:
|
|
27
|
+
```
|
|
28
|
+
User → Orchestrator → [ResearchAgent] → [WriterAgent] → Orchestrator → User
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Pipeline** — Agenten geben Ergebnisse der Reihe nach weiter:
|
|
32
|
+
```
|
|
33
|
+
User → Agent1(classify) → Agent2(extract) → Agent3(generate) → User
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Die einfachste Architektur wählen, die das Problem löst. Einzelner Agent mit Tools löst die meisten Fälle.
|
|
37
|
+
|
|
38
|
+
### Tool-Design
|
|
39
|
+
```python
|
|
40
|
+
# Tool-Definitionen für Multi-Turn-Agenten-Schleife
|
|
41
|
+
tools = [
|
|
42
|
+
{
|
|
43
|
+
"name": "search_web",
|
|
44
|
+
"description": "Search the web for current information. Use when you need facts not in your training data.",
|
|
45
|
+
"input_schema": {
|
|
46
|
+
"type": "object",
|
|
47
|
+
"properties": {
|
|
48
|
+
"query": {"type": "string", "description": "Search query"}
|
|
49
|
+
},
|
|
50
|
+
"required": ["query"]
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "read_file",
|
|
55
|
+
"description": "Read contents of a file by path.",
|
|
56
|
+
"input_schema": {
|
|
57
|
+
"type": "object",
|
|
58
|
+
"properties": {
|
|
59
|
+
"path": {"type": "string", "description": "Absolute file path"}
|
|
60
|
+
},
|
|
61
|
+
"required": ["path"]
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "write_file",
|
|
66
|
+
"description": "Write content to a file. Creates the file if it doesn't exist.",
|
|
67
|
+
"input_schema": {
|
|
68
|
+
"type": "object",
|
|
69
|
+
"properties": {
|
|
70
|
+
"path": {"type": "string"},
|
|
71
|
+
"content": {"type": "string"}
|
|
72
|
+
},
|
|
73
|
+
"required": ["path", "content"]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Tool-Design-Regeln:
|
|
80
|
+
- Die Beschreibung muss Claude mitteilen, WANN es verwendet werden soll, nicht nur was es tut
|
|
81
|
+
- `input_schema` minimal halten — nur erforderliche Felder, kein optionaler Lärm
|
|
82
|
+
- Strukturierte Daten zurückgeben (JSON), keine Prosa, damit Claude sie zuverlässig verwenden kann
|
|
83
|
+
- Ein Tool pro Aktion — Lesen+Schreiben nicht in ein Tool bündeln
|
|
84
|
+
|
|
85
|
+
### Agenten-Schleife
|
|
86
|
+
```python
|
|
87
|
+
import anthropic
|
|
88
|
+
import json
|
|
89
|
+
|
|
90
|
+
client = anthropic.Anthropic()
|
|
91
|
+
|
|
92
|
+
def run_agent(task: str, max_iterations: int = 20) -> str:
|
|
93
|
+
messages = [{"role": "user", "content": task}]
|
|
94
|
+
|
|
95
|
+
for iteration in range(max_iterations):
|
|
96
|
+
response = client.messages.create(
|
|
97
|
+
model="claude-sonnet-4-6",
|
|
98
|
+
max_tokens=4096,
|
|
99
|
+
system=AGENT_SYSTEM_PROMPT,
|
|
100
|
+
tools=tools,
|
|
101
|
+
messages=messages,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# Antwort des Assistenten anhängen
|
|
105
|
+
messages.append({"role": "assistant", "content": response.content})
|
|
106
|
+
|
|
107
|
+
if response.stop_reason == "end_turn":
|
|
108
|
+
# Finale Textantwort extrahieren
|
|
109
|
+
return next(b.text for b in response.content if hasattr(b, "text"))
|
|
110
|
+
|
|
111
|
+
if response.stop_reason == "tool_use":
|
|
112
|
+
# Alle Tool-Aufrufe in dieser Antwort ausführen
|
|
113
|
+
tool_results = []
|
|
114
|
+
for block in response.content:
|
|
115
|
+
if block.type == "tool_use":
|
|
116
|
+
result = execute_tool(block.name, block.input)
|
|
117
|
+
tool_results.append({
|
|
118
|
+
"type": "tool_result",
|
|
119
|
+
"tool_use_id": block.id,
|
|
120
|
+
"content": json.dumps(result) if not isinstance(result, str) else result
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
messages.append({"role": "user", "content": tool_results})
|
|
124
|
+
else:
|
|
125
|
+
# Unerwarteter Stopp-Grund
|
|
126
|
+
break
|
|
127
|
+
|
|
128
|
+
raise RuntimeError(f"Agent exceeded {max_iterations} iterations without completing")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def execute_tool(name: str, inputs: dict) -> any:
|
|
132
|
+
match name:
|
|
133
|
+
case "search_web":
|
|
134
|
+
return search(inputs["query"])
|
|
135
|
+
case "read_file":
|
|
136
|
+
return Path(inputs["path"]).read_text()
|
|
137
|
+
case "write_file":
|
|
138
|
+
Path(inputs["path"]).write_text(inputs["content"])
|
|
139
|
+
return {"success": True, "path": inputs["path"]}
|
|
140
|
+
case _:
|
|
141
|
+
return {"error": f"Unknown tool: {name}"}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### System-Prompt für Agenten
|
|
145
|
+
```
|
|
146
|
+
AGENT_SYSTEM_PROMPT = """You are an autonomous agent completing tasks step by step.
|
|
147
|
+
|
|
148
|
+
Approach:
|
|
149
|
+
1. Analyze the task before acting
|
|
150
|
+
2. Use the minimum tools necessary
|
|
151
|
+
3. Check your work before declaring done
|
|
152
|
+
4. If a tool returns an error, diagnose and retry once — if it fails again, report the error
|
|
153
|
+
|
|
154
|
+
Stopping conditions — declare "DONE: <result>" when:
|
|
155
|
+
- The task is fully complete
|
|
156
|
+
- You've hit an unrecoverable error after retrying
|
|
157
|
+
- You've been asked to do something harmful or impossible
|
|
158
|
+
|
|
159
|
+
Never loop more than 3 times on the same tool call with the same inputs.
|
|
160
|
+
"""
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Speichermuster
|
|
164
|
+
|
|
165
|
+
**In-Kontext-Speicher** (Nachrichten-Array) — für einzelne Sitzung, kleinen State:
|
|
166
|
+
```python
|
|
167
|
+
# Zusammenfassen wenn Kontext zu groß wird
|
|
168
|
+
if count_tokens(messages) > 150_000:
|
|
169
|
+
summary = summarize_messages(messages[:-5]) # letzte 5 Turns behalten
|
|
170
|
+
messages = [
|
|
171
|
+
{"role": "user", "content": f"[Previous context summary]\n{summary}"},
|
|
172
|
+
{"role": "assistant", "content": "Understood. Continuing from where we left off."},
|
|
173
|
+
*messages[-5:]
|
|
174
|
+
]
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Externer Speicher** (für Multi-Session-Agenten):
|
|
178
|
+
```python
|
|
179
|
+
# Einfacher dateibasierter Speicher
|
|
180
|
+
class AgentMemory:
|
|
181
|
+
def __init__(self, path: str):
|
|
182
|
+
self.path = Path(path)
|
|
183
|
+
self.data = json.loads(self.path.read_text()) if self.path.exists() else {}
|
|
184
|
+
|
|
185
|
+
def remember(self, key: str, value: any):
|
|
186
|
+
self.data[key] = {"value": value, "timestamp": datetime.utcnow().isoformat()}
|
|
187
|
+
self.path.write_text(json.dumps(self.data, indent=2))
|
|
188
|
+
|
|
189
|
+
def recall(self, key: str) -> any:
|
|
190
|
+
entry = self.data.get(key)
|
|
191
|
+
return entry["value"] if entry else None
|
|
192
|
+
|
|
193
|
+
def as_context(self) -> str:
|
|
194
|
+
if not self.data:
|
|
195
|
+
return ""
|
|
196
|
+
lines = [f"- {k}: {v['value']}" for k, v in self.data.items()]
|
|
197
|
+
return "Known context:\n" + "\n".join(lines)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Orchestrator-Muster
|
|
201
|
+
```python
|
|
202
|
+
def orchestrate(task: str) -> str:
|
|
203
|
+
# Schritt 1: Planungs-Agent zerlegt die Aufgabe
|
|
204
|
+
plan = run_subagent(
|
|
205
|
+
model="claude-sonnet-4-6",
|
|
206
|
+
system="You are a planner. Decompose tasks into numbered steps.",
|
|
207
|
+
task=f"Decompose this task into steps: {task}",
|
|
208
|
+
tools=[] # Keine Tools für die Planung benötigt
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
# Schritt 2: Jeden Schritt mit spezialisierten Agenten ausführen
|
|
212
|
+
results = []
|
|
213
|
+
for step in parse_steps(plan):
|
|
214
|
+
agent_type = classify_step(step) # "research" | "code" | "write"
|
|
215
|
+
result = run_subagent(
|
|
216
|
+
model=agent_model(agent_type),
|
|
217
|
+
system=agent_system_prompt(agent_type),
|
|
218
|
+
task=step,
|
|
219
|
+
tools=agent_tools(agent_type),
|
|
220
|
+
context="\n".join(results) # Kontext aus vorherigen Schritten mitgeben
|
|
221
|
+
)
|
|
222
|
+
results.append(f"Step result: {result}")
|
|
223
|
+
|
|
224
|
+
# Schritt 3: Synthese-Agent kombiniert Ergebnisse
|
|
225
|
+
return run_subagent(
|
|
226
|
+
model="claude-sonnet-4-6",
|
|
227
|
+
system="You are a synthesizer. Combine step results into a final answer.",
|
|
228
|
+
task=f"Original task: {task}\n\nStep results:\n" + "\n".join(results),
|
|
229
|
+
tools=[]
|
|
230
|
+
)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Fehlerbehandlung und Abbruchbedingungen
|
|
234
|
+
```python
|
|
235
|
+
class AgentError(Exception):
|
|
236
|
+
pass
|
|
237
|
+
|
|
238
|
+
class MaxIterationsError(AgentError):
|
|
239
|
+
pass
|
|
240
|
+
|
|
241
|
+
class ToolFailureError(AgentError):
|
|
242
|
+
pass
|
|
243
|
+
|
|
244
|
+
def execute_tool_safe(name: str, inputs: dict, consecutive_failures: dict) -> dict:
|
|
245
|
+
try:
|
|
246
|
+
result = execute_tool(name, inputs)
|
|
247
|
+
consecutive_failures[name] = 0
|
|
248
|
+
return {"success": True, "result": result}
|
|
249
|
+
except Exception as e:
|
|
250
|
+
consecutive_failures[name] = consecutive_failures.get(name, 0) + 1
|
|
251
|
+
if consecutive_failures[name] >= 3:
|
|
252
|
+
raise ToolFailureError(f"Tool {name} failed 3 consecutive times: {e}")
|
|
253
|
+
return {"success": False, "error": str(e), "retry": True}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Handoff-Muster
|
|
257
|
+
```python
|
|
258
|
+
# Eltern-Agent übergibt Kontext explizit — Subagenten haben keinen Session-Speicher
|
|
259
|
+
def handoff_to_specialist(context: dict, task: str, specialist: str) -> str:
|
|
260
|
+
handoff_prompt = f"""
|
|
261
|
+
Context from orchestrator:
|
|
262
|
+
{json.dumps(context, indent=2)}
|
|
263
|
+
|
|
264
|
+
Your task:
|
|
265
|
+
{task}
|
|
266
|
+
"""
|
|
267
|
+
return run_subagent(
|
|
268
|
+
system=SPECIALIST_PROMPTS[specialist],
|
|
269
|
+
task=handoff_prompt,
|
|
270
|
+
tools=SPECIALIST_TOOLS[specialist]
|
|
271
|
+
)
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Beispiel
|
|
275
|
+
|
|
276
|
+
**Benutzer:** Einen Recherche-Agenten bauen, der ein Thema annimmt, das Web nach 3 Quellen durchsucht, jede URL liest und eine 500-Wörter-Zusammenfassung mit Zitaten in eine Datei schreibt.
|
|
277
|
+
|
|
278
|
+
**Erwartete Ausgabe:**
|
|
279
|
+
- `tools`-Liste: `search_web`, `fetch_url`, `write_file`
|
|
280
|
+
- System-Prompt: weist Agenten an, zu suchen → 3 URLs abrufen → synthetisieren → Datei schreiben, bevor fertig erklärt wird
|
|
281
|
+
- `run_agent(task)`-Schleife mit `max_iterations=15`
|
|
282
|
+
- Fehlerbehandlung: wenn `fetch_url` scheitert, nächstes Suchergebnis versuchen
|
|
283
|
+
- Finale Ausgabe: Pfad zur geschriebenen Zusammenfassungsdatei
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
> **Mit uns arbeiten:** Claudient wird von [Uitbreiden](https://uitbreiden.com/) unterstützt — wir bauen KI-Produkte und B2B-Lösungen mit Entwickler-Communities. [uitbreiden.com](https://uitbreiden.com/)
|