mirror of
https://github.com/anthropics/skills.git
synced 2026-08-02 21:15:27 +08:00
Add Opus 4.8 migration guide and model updates to claude-api skill (#1216)
* Add Managed Agents self-hosted sandboxes + mid-session agent updates + MCP tool-output offload to claude-api skill
Self-hosted sandboxes: new shared/managed-agents-self-hosted-sandboxes.md for config:{type:"self_hosted"} — agent loop on Anthropic's orchestration, tool execution on customer infra via outbound-polling worker. Covers EnvironmentWorker.run()/.run_one() (Py/TS), ant beta:worker poll/run, mid-level work.poller()/WorkPoller (Py/TS/Go only; Go has no auto_stop opt-out), AgentToolContext/beta_agent_toolset/tool_runner(), monitoring (environments.work.stats/stop — x-api-key, call from outside worker host), runtime deps, cloud-vs-self_hosted delta table, credentials, security ownership split. Cross-refs in environments.md, overview.md (Reading Guide + rewrote cloud-only pitfall), api-reference.md (SDK row + naming-quirks + schema + work REST rows), tools.md (Who-runs-it carve-out), onboarding.md, live-sources.md.
Mid-session agent updates: sessions.update(session_id, agent={tools, mcp_servers}, vault_ids=[...]) — session-local override (doesn't bump agent version), full-replacement semantics, session must be idle. New core.md section + pointers in tools.md, api-reference.md (UpdateSession row), overview.md.
Large MCP tool outputs → files: >100K tokens → automatic offload to sandbox file; agent gets truncated preview + path. Plus: invalid vault credentials don't block sessions.create() — session.error event fires, auth retries on next idle→running. Both in tools.md.
* Point ant CLI install ref to live-sources.md (OSS has no anthropic-cli.md)
* Add Opus 4.8 model migration guide to claude-api skill
* Add prescriptive tool-description guidance for Opus 4.8 to claude-api skill
This commit is contained in:
@@ -27,7 +27,7 @@ async_client = anthropic.AsyncAnthropic()
|
||||
|
||||
```python
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[
|
||||
{"role": "user", "content": "What is the capital of France?"}
|
||||
@@ -46,7 +46,7 @@ for block in response.content:
|
||||
|
||||
```python
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
system="You are a helpful coding assistant. Always provide examples in Python.",
|
||||
messages=[{"role": "user", "content": "How do I read a JSON file?"}]
|
||||
@@ -66,7 +66,7 @@ with open("image.png", "rb") as f:
|
||||
image_data = base64.standard_b64encode(f.read()).decode("utf-8")
|
||||
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{
|
||||
"role": "user",
|
||||
@@ -89,7 +89,7 @@ response = client.messages.create(
|
||||
|
||||
```python
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{
|
||||
"role": "user",
|
||||
@@ -119,7 +119,7 @@ Use top-level `cache_control` to automatically cache the last cacheable block in
|
||||
|
||||
```python
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
cache_control={"type": "ephemeral"}, # auto-caches the last cacheable block
|
||||
system="You are an expert on this large document...",
|
||||
@@ -133,7 +133,7 @@ For fine-grained control, add `cache_control` to specific content blocks:
|
||||
|
||||
```python
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
system=[{
|
||||
"type": "text",
|
||||
@@ -145,7 +145,7 @@ response = client.messages.create(
|
||||
|
||||
# With explicit TTL (time-to-live)
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
system=[{
|
||||
"type": "text",
|
||||
@@ -170,13 +170,13 @@ If `cache_read_input_tokens` is zero across repeated identical-prefix requests,
|
||||
|
||||
## Extended Thinking
|
||||
|
||||
> **Opus 4.7, Opus 4.6, and Sonnet 4.6:** Use adaptive thinking. `budget_tokens` is removed on Opus 4.7 (400 if sent); deprecated on Opus 4.6 and Sonnet 4.6.
|
||||
> **Opus 4.8, Opus 4.7, Opus 4.6, and Sonnet 4.6:** Use adaptive thinking. `budget_tokens` is removed on Opus 4.8 and 4.7 (400 if sent); deprecated on Opus 4.6 and Sonnet 4.6.
|
||||
> **Older models:** Use `thinking: {type: "enabled", budget_tokens: N}` (must be < `max_tokens`, min 1024).
|
||||
|
||||
```python
|
||||
# Opus 4.7 / 4.6: adaptive thinking (recommended)
|
||||
# Opus 4.8 / 4.7 / 4.6: adaptive thinking (recommended)
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
thinking={"type": "adaptive"},
|
||||
output_config={"effort": "high"}, # low | medium | high | max
|
||||
@@ -258,7 +258,7 @@ class ConversationManager:
|
||||
# Usage
|
||||
conversation = ConversationManager(
|
||||
client=anthropic.Anthropic(),
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
system="You are a helpful assistant."
|
||||
)
|
||||
|
||||
@@ -275,7 +275,7 @@ response2 = conversation.send("What's my name?") # Claude remembers "Alice"
|
||||
|
||||
### Compaction (long conversations)
|
||||
|
||||
> **Beta, Opus 4.7, Opus 4.6, and Sonnet 4.6.** When conversations approach the 200K context window, compaction automatically summarizes earlier context server-side. The API returns a `compaction` block; you must pass it back on subsequent requests — append `response.content`, not just the text.
|
||||
> **Beta, Opus 4.8, Opus 4.7, Opus 4.6, and Sonnet 4.6.** When conversations approach the 200K context window, compaction automatically summarizes earlier context server-side. The API returns a `compaction` block; you must pass it back on subsequent requests — append `response.content`, not just the text.
|
||||
|
||||
```python
|
||||
import anthropic
|
||||
@@ -288,7 +288,7 @@ def chat(user_message: str) -> str:
|
||||
|
||||
response = client.beta.messages.create(
|
||||
betas=["compact-2026-01-12"],
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=messages,
|
||||
context_management={
|
||||
@@ -331,7 +331,7 @@ The `stop_reason` field in the response indicates why the model stopped generati
|
||||
```python
|
||||
# Automatic caching (simplest — caches the last cacheable block)
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
cache_control={"type": "ephemeral"},
|
||||
system=large_document_text, # e.g., 50KB of context
|
||||
@@ -347,7 +347,7 @@ response = client.messages.create(
|
||||
```python
|
||||
# Default to Opus for most tasks
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7", # $5.00/$25.00 per 1M tokens
|
||||
model="claude-opus-4-8", # $5.00/$25.00 per 1M tokens
|
||||
max_tokens=16000,
|
||||
messages=[{"role": "user", "content": "Explain quantum computing"}]
|
||||
)
|
||||
@@ -371,7 +371,7 @@ simple_response = client.messages.create(
|
||||
|
||||
```python
|
||||
count_response = client.messages.count_tokens(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
messages=messages,
|
||||
system=system
|
||||
)
|
||||
|
||||
@@ -26,7 +26,7 @@ message_batch = client.messages.batches.create(
|
||||
Request(
|
||||
custom_id="request-1",
|
||||
params=MessageCreateParamsNonStreaming(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{"role": "user", "content": "Summarize climate change impacts"}]
|
||||
)
|
||||
@@ -34,7 +34,7 @@ message_batch = client.messages.batches.create(
|
||||
Request(
|
||||
custom_id="request-2",
|
||||
params=MessageCreateParamsNonStreaming(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{"role": "user", "content": "Explain quantum computing basics"}]
|
||||
)
|
||||
@@ -117,7 +117,7 @@ message_batch = client.messages.batches.create(
|
||||
Request(
|
||||
custom_id=f"analysis-{i}",
|
||||
params=MessageCreateParamsNonStreaming(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
system=shared_system,
|
||||
messages=[{"role": "user", "content": question}]
|
||||
|
||||
@@ -36,7 +36,7 @@ print(f"Size: {uploaded.size_bytes} bytes")
|
||||
|
||||
```python
|
||||
response = client.beta.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{
|
||||
"role": "user",
|
||||
@@ -65,7 +65,7 @@ image_file = client.beta.files.upload(
|
||||
)
|
||||
|
||||
response = client.beta.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{
|
||||
"role": "user",
|
||||
@@ -142,7 +142,7 @@ questions = [
|
||||
|
||||
for question in questions:
|
||||
response = client.beta.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{
|
||||
"role": "user",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
```python
|
||||
with client.messages.stream(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=64000,
|
||||
messages=[{"role": "user", "content": "Write a story"}]
|
||||
) as stream:
|
||||
@@ -16,7 +16,7 @@ with client.messages.stream(
|
||||
|
||||
```python
|
||||
async with async_client.messages.stream(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=64000,
|
||||
messages=[{"role": "user", "content": "Write a story"}]
|
||||
) as stream:
|
||||
@@ -30,11 +30,11 @@ async with async_client.messages.stream(
|
||||
|
||||
Claude may return text, thinking blocks, or tool use. Handle each appropriately:
|
||||
|
||||
> **Opus 4.7 / Opus 4.6:** Use `thinking: {type: "adaptive"}`. On older models, use `thinking: {type: "enabled", budget_tokens: N}` instead.
|
||||
> **Opus 4.8 / Opus 4.7 / Opus 4.6:** Use `thinking: {type: "adaptive"}`. On older models, use `thinking: {type: "enabled", budget_tokens: N}` instead.
|
||||
|
||||
```python
|
||||
with client.messages.stream(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=64000,
|
||||
thinking={"type": "adaptive"},
|
||||
messages=[{"role": "user", "content": "Analyze this problem"}]
|
||||
@@ -61,7 +61,7 @@ The Python tool runner currently returns complete messages. Use streaming for in
|
||||
|
||||
```python
|
||||
with client.messages.stream(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=64000,
|
||||
tools=tools,
|
||||
messages=messages
|
||||
@@ -79,7 +79,7 @@ with client.messages.stream(
|
||||
|
||||
```python
|
||||
with client.messages.stream(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=64000,
|
||||
messages=[{"role": "user", "content": "Hello"}]
|
||||
) as stream:
|
||||
@@ -126,7 +126,7 @@ def stream_with_progress(client, **kwargs):
|
||||
```python
|
||||
try:
|
||||
with client.messages.stream(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=64000,
|
||||
messages=[{"role": "user", "content": "Write a story"}]
|
||||
) as stream:
|
||||
|
||||
@@ -27,7 +27,7 @@ def get_weather(location: str, unit: str = "celsius") -> str:
|
||||
|
||||
# The tool runner handles the agentic loop automatically
|
||||
runner = client.beta.messages.tool_runner(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
tools=[get_weather],
|
||||
messages=[{"role": "user", "content": "What's the weather in Paris?"}],
|
||||
@@ -72,7 +72,7 @@ async with stdio_client(StdioServerParameters(command="mcp-server")) as (read, w
|
||||
tools_result = await mcp_client.list_tools()
|
||||
# tool_runner is sync — returns the runner, not a coroutine
|
||||
runner = client.beta.messages.tool_runner(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{"role": "user", "content": "Use the available tools"}],
|
||||
tools=[async_mcp_tool(t, mcp_client) for t in tools_result.tools],
|
||||
@@ -90,7 +90,7 @@ from anthropic.lib.tools.mcp import mcp_message
|
||||
|
||||
prompt = await mcp_client.get_prompt(name="my-prompt")
|
||||
response = await client.beta.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[mcp_message(m) for m in prompt.messages],
|
||||
)
|
||||
@@ -103,7 +103,7 @@ from anthropic.lib.tools.mcp import mcp_resource_to_content
|
||||
|
||||
resource = await mcp_client.read_resource(uri="file:///path/to/doc.txt")
|
||||
response = await client.beta.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{
|
||||
"role": "user",
|
||||
@@ -142,7 +142,7 @@ messages = [{"role": "user", "content": user_input}]
|
||||
# Agentic loop: keep going until Claude stops calling tools
|
||||
while True:
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
tools=tools,
|
||||
messages=messages
|
||||
@@ -189,7 +189,7 @@ final_text = next(b.text for b in response.content if b.type == "text")
|
||||
|
||||
```python
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
tools=tools,
|
||||
messages=[{"role": "user", "content": "What's the weather in Paris?"}]
|
||||
@@ -204,7 +204,7 @@ for block in response.content:
|
||||
result = execute_tool(tool_name, tool_input)
|
||||
|
||||
followup = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
tools=tools,
|
||||
messages=[
|
||||
@@ -241,7 +241,7 @@ for block in response.content:
|
||||
# Send all results back at once
|
||||
if tool_results:
|
||||
followup = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
tools=tools,
|
||||
messages=[
|
||||
@@ -271,7 +271,7 @@ tool_result = {
|
||||
|
||||
```python
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
tools=tools,
|
||||
tool_choice={"type": "tool", "name": "get_weather"}, # Force specific tool
|
||||
@@ -291,7 +291,7 @@ import anthropic
|
||||
client = anthropic.Anthropic()
|
||||
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{
|
||||
"role": "user",
|
||||
@@ -319,7 +319,7 @@ uploaded = client.beta.files.upload(file=open("sales_data.csv", "rb"))
|
||||
# 2. Pass to code execution via container_upload block
|
||||
# Code execution is GA; Files API is still beta (pass via extra_headers)
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
extra_headers={"anthropic-beta": "files-api-2025-04-14"},
|
||||
messages=[{
|
||||
@@ -364,7 +364,7 @@ for block in response.content:
|
||||
```python
|
||||
# First request: set up environment
|
||||
response1 = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{"role": "user", "content": "Install tabulate and create data.json with sample data"}],
|
||||
tools=[{"type": "code_execution_20260120", "name": "code_execution"}]
|
||||
@@ -376,7 +376,7 @@ container_id = response1.container.id
|
||||
# Second request: reuse the same container
|
||||
response2 = client.messages.create(
|
||||
container=container_id,
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{"role": "user", "content": "Read data.json and display as a formatted table"}],
|
||||
tools=[{"type": "code_execution_20260120", "name": "code_execution"}]
|
||||
@@ -416,7 +416,7 @@ import anthropic
|
||||
client = anthropic.Anthropic()
|
||||
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{"role": "user", "content": "Remember that my preferred language is Python."}],
|
||||
tools=[{"type": "memory_20250818", "name": "memory"}],
|
||||
@@ -442,7 +442,7 @@ memory = MyMemoryTool()
|
||||
|
||||
# Use with tool runner
|
||||
runner = client.beta.messages.tool_runner(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
tools=[memory],
|
||||
messages=[{"role": "user", "content": "Remember my preferences"}],
|
||||
@@ -477,7 +477,7 @@ class ContactInfo(BaseModel):
|
||||
client = anthropic.Anthropic()
|
||||
|
||||
response = client.messages.parse(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{
|
||||
"role": "user",
|
||||
@@ -496,7 +496,7 @@ print(contact.interests) # ["API", "SDKs"]
|
||||
|
||||
```python
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{
|
||||
"role": "user",
|
||||
@@ -530,7 +530,7 @@ data = json.loads(text)
|
||||
|
||||
```python
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{"role": "user", "content": "Book a flight to Tokyo for 2 passengers on March 15"}],
|
||||
tools=[{
|
||||
@@ -555,7 +555,7 @@ response = client.messages.create(
|
||||
|
||||
```python
|
||||
response = client.messages.create(
|
||||
model="claude-opus-4-7",
|
||||
model="claude-opus-4-8",
|
||||
max_tokens=16000,
|
||||
messages=[{"role": "user", "content": "Plan a trip to Paris next month"}],
|
||||
output_config={
|
||||
|
||||
Reference in New Issue
Block a user