Skip to content

Commit 06d5ac8

Browse files
edfragasclaude
andcommitted
Add migration samples from Anthropic code execution to AgentCore Code Interpreter
Includes 7 working examples covering Converse API, InvokeModel API, Strands SDK, high-level CodeInterpreter API, Claude Code in a sandbox, and prompt caching. All scripts tested against a live AWS account. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 5b09f23 commit 06d5ac8

11 files changed

Lines changed: 1357 additions & 0 deletions
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""
2+
00 - Anthropic Code Execution Tool (BEFORE - Reference)
3+
4+
This is the ORIGINAL Anthropic approach. One API call — Claude decides to execute
5+
code, runs it in a managed container, and returns the answer inline.
6+
No agentic loop. No tool-use handling. No session management.
7+
8+
This is what we are migrating FROM.
9+
10+
Requirements:
11+
pip install anthropic
12+
13+
Usage:
14+
export ANTHROPIC_API_KEY=your_key
15+
python 00_anthropic_code_execution.py
16+
"""
17+
18+
import anthropic
19+
20+
client = anthropic.Anthropic()
21+
22+
# One API call — Claude handles everything server-side
23+
response = client.beta.messages.create(
24+
model="claude-sonnet-4-5-20250929",
25+
betas=["code-execution-2025-08-25"],
26+
max_tokens=4096,
27+
messages=[{
28+
"role": "user",
29+
"content": "Calculate the mean and standard deviation of "
30+
"[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"
31+
}],
32+
tools=[{
33+
"type": "code_execution_20250825",
34+
"name": "code_execution"
35+
}]
36+
)
37+
38+
# Results are inline — no loop needed
39+
for block in response.content:
40+
if block.type == "text":
41+
print(block.text)
42+
elif block.type == "code_execution_tool_result":
43+
print(f"[Code Output] {block.content}")
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
"""
2+
01 - Bedrock Converse API + AgentCore Code Interpreter
3+
4+
This is the custom agentic loop approach using the Converse API.
5+
It wires together two AWS services:
6+
- Bedrock Runtime (Converse API) for Claude
7+
- AgentCore Code Interpreter for sandboxed code execution
8+
9+
The loop: Claude → tool_use? → execute code → return result → Claude → final answer.
10+
11+
Requirements:
12+
pip install boto3 bedrock-agentcore
13+
14+
Usage:
15+
# Configure AWS credentials (IAM, SSO, or environment variables)
16+
python 01_converse_api_with_code_interpreter.py
17+
"""
18+
19+
import boto3
20+
21+
# --- Configuration ---
22+
REGION = "us-west-2"
23+
MODEL_ID = "global.anthropic.claude-sonnet-4-6"
24+
25+
# --- AWS Clients ---
26+
bedrock = boto3.client("bedrock-runtime", region_name=REGION)
27+
agentcore = boto3.client("bedrock-agentcore", region_name=REGION)
28+
29+
# --- Tool definition for Claude ---
30+
tool_config = {
31+
"tools": [{
32+
"toolSpec": {
33+
"name": "execute_python",
34+
"description": (
35+
"Execute Python code in a secure sandbox. "
36+
"Use this for calculations, data analysis, or to verify results. "
37+
"Common libraries like numpy, pandas, and matplotlib are available."
38+
),
39+
"inputSchema": {
40+
"json": {
41+
"type": "object",
42+
"properties": {
43+
"code": {
44+
"type": "string",
45+
"description": "Python code to execute"
46+
}
47+
},
48+
"required": ["code"]
49+
}
50+
}
51+
}
52+
}]
53+
}
54+
55+
56+
def execute_code(code: str, session_id: str) -> str:
57+
"""Execute code via AgentCore and return the output."""
58+
response = agentcore.invoke_code_interpreter(
59+
codeInterpreterIdentifier="aws.codeinterpreter.v1",
60+
sessionId=session_id,
61+
name="executeCode",
62+
arguments={"language": "python", "code": code}
63+
)
64+
parts = []
65+
for event in response["stream"]:
66+
if "result" in event:
67+
for item in event["result"].get("content", []):
68+
if item["type"] == "text":
69+
parts.append(item["text"])
70+
return "\n".join(parts)
71+
72+
73+
def converse_with_code_execution(user_message: str) -> str:
74+
"""Full agentic loop: Converse API + AgentCore Code Interpreter."""
75+
76+
# Start a code interpreter session
77+
session = agentcore.start_code_interpreter_session(
78+
codeInterpreterIdentifier="aws.codeinterpreter.v1",
79+
name="converse-session",
80+
sessionTimeoutSeconds=900
81+
)
82+
session_id = session["sessionId"]
83+
print(f"[Session started: {session_id}]")
84+
85+
messages = [{"role": "user", "content": [{"text": user_message}]}]
86+
87+
try:
88+
while True:
89+
# Step 1: Call Claude via Converse API
90+
response = bedrock.converse(
91+
modelId=MODEL_ID,
92+
messages=messages,
93+
toolConfig=tool_config,
94+
inferenceConfig={"maxTokens": 4096}
95+
)
96+
97+
assistant_msg = response["output"]["message"]
98+
messages.append(assistant_msg)
99+
100+
# Step 2: If Claude is done (no tool request), return the answer
101+
if response["stopReason"] != "tool_use":
102+
break
103+
104+
# Step 3: Execute any requested tools
105+
tool_results = []
106+
for block in assistant_msg["content"]:
107+
if "toolUse" in block:
108+
tool = block["toolUse"]
109+
print(f"[Executing code...]")
110+
try:
111+
result = execute_code(tool["input"]["code"], session_id)
112+
print(f"[Code output: {result[:100]}...]")
113+
tool_results.append({
114+
"toolResult": {
115+
"toolUseId": tool["toolUseId"],
116+
"content": [{"text": result}],
117+
"status": "success"
118+
}
119+
})
120+
except Exception as e:
121+
tool_results.append({
122+
"toolResult": {
123+
"toolUseId": tool["toolUseId"],
124+
"content": [{"text": str(e)}],
125+
"status": "error"
126+
}
127+
})
128+
129+
# Step 4: Send tool results back to Claude and loop
130+
messages.append({"role": "user", "content": tool_results})
131+
132+
# Extract final text response
133+
return "\n".join(
134+
b["text"] for b in assistant_msg["content"] if "text" in b
135+
)
136+
137+
finally:
138+
# Always clean up the session
139+
agentcore.stop_code_interpreter_session(
140+
codeInterpreterIdentifier="aws.codeinterpreter.v1",
141+
sessionId=session_id
142+
)
143+
print(f"[Session stopped: {session_id}]")
144+
145+
146+
# --- Run ---
147+
if __name__ == "__main__":
148+
answer = converse_with_code_execution(
149+
"Calculate the mean and standard deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"
150+
)
151+
print("\n--- Final Answer ---")
152+
print(answer)
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
"""
2+
02 - Bedrock InvokeModel API + AgentCore Code Interpreter
3+
4+
This approach uses the InvokeModel API with the native Anthropic Messages format.
5+
The request body is nearly identical to what you'd send to api.anthropic.com,
6+
making it the easiest path to minimize changes to existing Anthropic code.
7+
8+
The agentic loop is the same as the Converse API version, but the request/response
9+
format matches the native Anthropic format.
10+
11+
Requirements:
12+
pip install boto3 bedrock-agentcore
13+
14+
Usage:
15+
# Configure AWS credentials (IAM, SSO, or environment variables)
16+
python 02_invoke_model_with_code_interpreter.py
17+
"""
18+
19+
import boto3
20+
import json
21+
22+
# --- Configuration ---
23+
REGION = "us-west-2"
24+
MODEL_ID = "global.anthropic.claude-sonnet-4-6"
25+
26+
# --- AWS Clients ---
27+
bedrock = boto3.client("bedrock-runtime", region_name=REGION)
28+
agentcore = boto3.client("bedrock-agentcore", region_name=REGION)
29+
30+
# --- Tool definition (native Anthropic format) ---
31+
TOOLS = [{
32+
"name": "execute_python",
33+
"description": (
34+
"Execute Python code in a secure sandbox. "
35+
"Use this for calculations, data analysis, or to verify results. "
36+
"Common libraries like numpy, pandas, and matplotlib are available."
37+
),
38+
"input_schema": {
39+
"type": "object",
40+
"properties": {
41+
"code": {
42+
"type": "string",
43+
"description": "Python code to execute"
44+
}
45+
},
46+
"required": ["code"]
47+
}
48+
}]
49+
50+
51+
def execute_code(code: str, session_id: str) -> str:
52+
"""Execute code via AgentCore and return the output."""
53+
response = agentcore.invoke_code_interpreter(
54+
codeInterpreterIdentifier="aws.codeinterpreter.v1",
55+
sessionId=session_id,
56+
name="executeCode",
57+
arguments={"language": "python", "code": code}
58+
)
59+
parts = []
60+
for event in response["stream"]:
61+
if "result" in event:
62+
for item in event["result"].get("content", []):
63+
if item["type"] == "text":
64+
parts.append(item["text"])
65+
return "\n".join(parts)
66+
67+
68+
def invoke_model_with_code_execution(user_message: str) -> str:
69+
"""Full agentic loop: InvokeModel API + AgentCore Code Interpreter."""
70+
71+
# Start a code interpreter session
72+
session = agentcore.start_code_interpreter_session(
73+
codeInterpreterIdentifier="aws.codeinterpreter.v1",
74+
name="invoke-model-session",
75+
sessionTimeoutSeconds=900
76+
)
77+
session_id = session["sessionId"]
78+
print(f"[Session started: {session_id}]")
79+
80+
messages = [{"role": "user", "content": [{"type": "text", "text": user_message}]}]
81+
82+
try:
83+
while True:
84+
# Step 1: Call Claude via InvokeModel (native Anthropic format)
85+
request_body = {
86+
"anthropic_version": "bedrock-2023-05-31",
87+
"max_tokens": 4096,
88+
"messages": messages,
89+
"tools": TOOLS
90+
}
91+
92+
response = bedrock.invoke_model(
93+
modelId=MODEL_ID,
94+
body=json.dumps(request_body),
95+
contentType="application/json",
96+
accept="application/json"
97+
)
98+
99+
result = json.loads(response["body"].read())
100+
101+
# Add assistant response to conversation
102+
messages.append({"role": "assistant", "content": result["content"]})
103+
104+
# Step 2: If Claude is done (no tool request), return the answer
105+
if result["stop_reason"] != "tool_use":
106+
break
107+
108+
# Step 3: Execute any requested tools
109+
tool_results = []
110+
for block in result["content"]:
111+
if block["type"] == "tool_use":
112+
print(f"[Executing code...]")
113+
try:
114+
output = execute_code(block["input"]["code"], session_id)
115+
print(f"[Code output: {output[:100]}...]")
116+
tool_results.append({
117+
"type": "tool_result",
118+
"tool_use_id": block["id"],
119+
"content": [{"type": "text", "text": output}]
120+
})
121+
except Exception as e:
122+
tool_results.append({
123+
"type": "tool_result",
124+
"tool_use_id": block["id"],
125+
"content": [{"type": "text", "text": str(e)}],
126+
"is_error": True
127+
})
128+
129+
# Step 4: Send tool results back to Claude and loop
130+
messages.append({"role": "user", "content": tool_results})
131+
132+
# Extract final text response
133+
return "\n".join(
134+
b["text"] for b in result["content"] if b["type"] == "text"
135+
)
136+
137+
finally:
138+
# Always clean up the session
139+
agentcore.stop_code_interpreter_session(
140+
codeInterpreterIdentifier="aws.codeinterpreter.v1",
141+
sessionId=session_id
142+
)
143+
print(f"[Session stopped: {session_id}]")
144+
145+
146+
# --- Run ---
147+
if __name__ == "__main__":
148+
answer = invoke_model_with_code_execution(
149+
"Calculate the mean and standard deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"
150+
)
151+
print("\n--- Final Answer ---")
152+
print(answer)

0 commit comments

Comments
 (0)