Amazon Bedrock AgentCoreを一通りさわり倒してみる ~ Code Interpreter 編 ~

ジェネラティブエージェンツの遠藤です。

先日発表されたAmazon Bedrock AgentCore、まさに「これ欲しかったやつ!!」の塊で、いろいろな機能を試すたびにテンションが爆上がりしています・・・!
その勢いで始めた『一通りさわり倒してみる』シリーズ、今回はCode Interpreter編になります。

今までの『一通りさわり倒してみる』シリーズもぜひご覧下さい。

blog.generative-agents.co.jp blog.generative-agents.co.jp

Code InterpreterはAgentCore built-in toolsと呼ばれる組み込みツール群のうちの一つで、エージェントがコードを安全に実行するためのサンドボックス環境をとても簡単に作ることができます。
例えばAIエージェントに何らかの計算を行わせたい場合に、プロンプトで頑張るより計算用のコードを生成させて実行したくなる時があります。
そういう時に困るのが「そのコード、どこで実行すれば・・・」という問題です。

仮に変なコードが生成された場合に備えて、生成されたコードはエージェントのプロセスやサーバとは隔離された環境で実行したくなります。
ただ、それを実現しようとすると専用のリードオンリーかつネットワークから隔離されたコンテナを作り込んでおき必要に応じてコードを組み込んで起動するなど、インフラ周りも含めて相当な作り込みが必要になります。

Code Interpreterの良いところは、そんな環境をプログラム上からさっと起動して動かせる所です。
RuntimeやMemoryの時も思いましたが、これがマネージド環境で提供されるのはほんと熱いですね・・・!

Code InterpreterはMemoryと違いすでにLangGraphとのインテグレーション例もあるので、この記事ではLangGraphと組み合わせた内容を紹介していきます。

AgentCore Code Interpreter

ざっくりと特徴をまとめると、以下のようになります。

  • 複数のプログラミング言語に対応(Python, JavaScript, TypeScriptなど)
  • 完全なサンドボックス環境かパブリックネットワーク環境かを選択可能
  • デフォルト15分、最長8時間までの長時間実行をサポート
  • 大容量ファイルのインラインアップロードやS3経由でアップロードサポートなど

エージェントに安全なコードをいかにして作らせるかといった課題はありますが、実行環境としてAWSがマネージドで守ってくれる環境があるのはとても良いですね!
色々なエージェントの実装を実験する上でも、インフラを気にせずに試行錯誤できそうなのでとてもワクワクします。
Code Interpreterにアップロードするファイルもインラインアップロードで最大100MB、S3にアップロードする場合は最大5GBと相当大きな物でもいけるようになっています。

細かな話は公式ドキュメントを是非ご覧下さい。

docs.aws.amazon.com

Code Interpreterでコードを実行してみる

はじめに、シンプルにCode InterpreterでPythonのコードを実行してみます。
ドキュメントに載ってるとおり、bedrock_agentcore.tools.code_interpreter_clientCodeInterpreterを利用すると簡単に実行することができます。
Code InterpreterはRuntimeにデプロイしなくても実行できるので、お手軽に試すためにローカルで実行していきます。

# agent_core_ci_hello.py
from bedrock_agentcore.tools.code_interpreter_client import CodeInterpreter
import json

code_client = CodeInterpreter('us-west-2')
code_client.start()
try:
    response = code_client.invoke("executeCode", {
        "language": "python", 
        "code": 'print("Hello AgentCore World!")'
    })

    for event in response["stream"]:
        print(json.dumps(event["result"], indent=2))
finally:
    code_client.stop()

上記のコードを実行すると、以下のようになります。

$ python agent_core_ci_hello.py
{
  "content": [
    {
      "type": "text",
      "text": "Hello AgentCore World!"
    }
  ],
  "structuredContent": {
    "stdout": "Hello AgentCore World!",
    "stderr": "",
    "exitCode": 0,
    "executionTime": 0.0236971378326416
  },
  "isError": false
}

コードの実行結果がcontentstructuredContentに分かれてるのが面白いですね。
特にstructuredContentexitCodeなども入ってるので、失敗した場合はリトライするとかもやりやすそうです。

なお、マネージメントコンソール上だと以下のように見えます。

マネージメントコンソール上のAgentCore Code Interpreter

エージェントからコードを実行してみる

次にエージェントにCode Interpreterをツールとして手渡して、Pythonのコードを実装して実行してみてもらいます。
ありがちですが、フィボナッチ数列を出力してみてもらいましょう。

# agent_core_code_interpreter.py
from bedrock_agentcore.tools.code_interpreter_client import code_session
from langchain.agents import tool
from langgraph.prebuilt import create_react_agent
import json


@tool
def execute_python(code: str) -> str:
    """Execute Python code in the sandbox."""

    with code_session("us-west-2") as code_client:
        response = code_client.invoke(
            "executeCode",
            {
                "code": code,
                "language": "python",
            },
        )

    return "\n".join(
        json.dumps(event["result"], indent=2) for event in response["stream"]
    )


agent = create_react_agent(
    model="anthropic:claude-opus-4-20250514",
    tools=[execute_python],
    prompt="You are a helpful assistant.",
)

result = agent.invoke(
    {"messages": [{"role": "user", "content": "Implement Python code that calculates the Fibonacci sequence and execute the code to output the first 10 numbers."}]}
)

print(result["messages"][-1].content)

上記のコードを実行すると以下のような結果が返ってきます。

$ python agent_core_code_interpreter.py
Perfect! I've successfully implemented and executed the Fibonacci sequence code. The first 10 numbers in the Fibonacci sequence are:

- F(0) = 0
- F(1) = 1
- F(2) = 1
- F(3) = 2
- F(4) = 3
- F(5) = 5
- F(6) = 8
- F(7) = 13
- F(8) = 21
- F(9) = 34

The Fibonacci sequence follows the pattern where each number is the sum of the two preceding numbers. Starting with 0 and 1, we get: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34...

The code includes a function that:
1. Handles edge cases (n ≤ 0, n = 1, n = 2)
2. Initializes the sequence with the first two numbers [0, 1]
3. Iteratively calculates each subsequent number by adding the previous two numbers
4. Returns the complete sequence as a list

狙い通りPythonのコードを実装して実行してくれたようです。
フィボナッチ数列としても正しい値が出力されてますね。

せっかくなのでresultの結果も覗いて、本当にCode Interpreterを利用してるのか確認してみましょう。

# result.py
{
    "messages": [
        HumanMessage(
            content="Implement Python code that calculates the Fibonacci sequence and execute the code to output the first 10 numbers.",
            ..
        ),
        AIMessage(
            content=[
                {
                    "text": "I'll implement a Python function to calculate the Fibonacci sequence and then execute it to show the first 10 numbers.",
                    "type": "text",
                },
                {
                    ...
                    "input": {
                        "code": 'def fibonacci(n):\n    """Generate the first n numbers in the Fibonacci sequence"""\n    if n <= 0:\n        return []\n    elif n == 1:\n        return [0]\n    elif n == 2:\n        return [0, 1]\n    \n    # Initialize the sequence with the first two numbers\n    fib_sequence = [0, 1]\n    \n    # Generate the rest of the sequence\n    for i in range(2, n):\n        next_number = fib_sequence[i-1] + fib_sequence[i-2]\n        fib_sequence.append(next_number)\n    \n    return fib_sequence\n\n# Calculate and display the first 10 Fibonacci numbers\nfirst_10 = fibonacci(10)\nprint("The first 10 numbers in the Fibonacci sequence are:")\nfor i, num in enumerate(first_10):\n    print(f"F({i}) = {num}")\n\n# Also display as a list\nprint(f"\\nAs a list: {first_10}")'
                    },
                    "name": "execute_python",
                    "type": "tool_use",
                },
            ],
            ...
            tool_calls=[
                {
                    "name": "execute_python",
                    "args": {
                        "code": 'def fibonacci(n):\n    """Generate the first n numbers in the Fibonacci sequence"""\n    if n <= 0:\n        return []\n    elif n == 1:\n        return [0]\n    elif n == 2:\n        return [0, 1]\n    \n    # Initialize the sequence with the first two numbers\n    fib_sequence = [0, 1]\n    \n    # Generate the rest of the sequence\n    for i in range(2, n):\n        next_number = fib_sequence[i-1] + fib_sequence[i-2]\n        fib_sequence.append(next_number)\n    \n    return fib_sequence\n\n# Calculate and display the first 10 Fibonacci numbers\nfirst_10 = fibonacci(10)\nprint("The first 10 numbers in the Fibonacci sequence are:")\nfor i, num in enumerate(first_10):\n    print(f"F({i}) = {num}")\n\n# Also display as a list\nprint(f"\\nAs a list: {first_10}")'
                    },
                    ...
                    "type": "tool_call",
                }
            ],
            ...
        ),
        ...
    ]
}

出力を全部載せるとだいぶ多いので省略してますが、ちゃんとtool_callsで生成したコードを渡して実行してました。
これだけ簡単にサンドボックス環境でエージェントにコードを実行させられるのは素敵ですね。

ネットワークに繋がる環境を作ってみる

今まで利用していたCode Interpreterの環境はAWSがデフォルトで準備してくれてるものでした。
詳細はドキュメントを見て頂きたいのですが、もっともセキュリティ的に厳しい設定になっています。

Code InterpreterではAWSが準備してくれているものとは別に、独自に作成したものも利用できるようになっています。
ここではマネージメントコンソールで作ってみようと思います。
他にもCLIやboto3、API経由で作成することができるので好みに合わせて作ってみてください。

まずはマネージメントコンソールで「Amazon Bedrock AgentCore」→「Built-in Tools」に移動して「Code interpreter tools」タブを表示します。

Code Interpreterの画面

そこで「Create」ボタンを押すと、以下の画面が表示されます。

Code Interpreterの新規作成画面

この画面で、ネットワークやIAMロールの設定が行えます。
エージェントが触れてもよい範囲を広くしたい場合、ここで調整が行えるようになってるんですね。

ここでは一旦ネットワークを「Public」にだけしたものを作ってみます。
作成が完了するとこんな形でマネージメントコンソールに表示されます。

ネットワークをPublicにしたCode Interpreter

エージェントにネットワークアクセスさせてみる

ここまでの作業でネットワークにアクセスできる環境ができたので、試しにエージェントにHEADリクエストを投げてもらいましょう。

自作したCode Interpreterを利用するには、セッションを開始する際にそのIDを指定する必要があります。
しかし、SDKのコードを読んだところ先ほど使ったwith code_session(...)のコンテキストマネージャではIDを指定できなそうでした。
そのため、以下のコードではCodeInterpreterクラスを直接インスタンス化し、start()メソッドにIDを渡す方法をとっています。

# agent_core_code_interpreter_public.py
from bedrock_agentcore.tools.code_interpreter_client import CodeInterpreter
from langchain.agents import tool
from langgraph.prebuilt import create_react_agent
import json


@tool
def execute_python(code: str) -> str:
    """Execute Python code in the sandbox."""

    code_client = CodeInterpreter('us-west-2')
    code_client.start(identifier="code_interpreter_tool_public-JMkcUanexd")
    try:
        response = code_client.invoke(
            "executeCode", 
            {
                "code": code,
                "language": "python",
            }
        )
    finally:
        code_client.stop()

    return "\n".join(
        json.dumps(event["result"], indent=2) for event in response["stream"]
    )



agent = create_react_agent(
    model="anthropic:claude-opus-4-20250514",
    tools=[execute_python],
    prompt="You are a helpful assistant.",
)

result = agent.invoke(
    {"messages": [{"role": "user", "content": "Implement code that sends a head request to the specified URL and obtains the response, then perform the processing for 'https://generative-agents.co.jp/' Take care to avoid SSL errors."}]}
)
print(result["messages"][-1].content)

上記のコードを実行すると以下のようになります。

$ python agent_core_code_interpreter_public.py
Perfect! I've successfully implemented code that:

1. **Sends a HEAD request** to https://generative-agents.co.jp/
2. **Handles SSL errors** by:
   - First attempting with SSL verification enabled
   - If SSL errors occur, automatically retrying without SSL verification
   - Disabling SSL warnings to avoid cluttering the output

3. **Key features of the implementation:**
   - Uses a session with retry strategy for reliability
   - Includes browser-like headers to avoid being blocked
   - Handles various types of errors gracefully
   - Returns comprehensive response information

4. **Results from the HEAD request:**
   - ✅ The site is accessible (HTTP 200 OK)
   - ✅ SSL certificate is valid (no SSL errors encountered)
   - The site is hosted on Fly.io infrastructure
   - Content is served as HTML with gzip compression
   - The server supports keep-alive connections

The code is production-ready and can be easily adapted for other URLs. It provides both the raw response data and a human-readable analysis of the results.

狙った通りにHEADリクエストを行ってくれてますね。
詳細が気になる方はぜひresultの結果を覗いてみると色々見えて面白いんじゃないかと思います。

ただ、1点注意というか経過観察しないとなーという点がありました。
エージェントの吐き出すコードの問題かCode Interpreterの設定の問題かの切り分けはまだできてないのですが、処理が上手くできないのかタイムアウトしてしまうことがぼちぼちありました。
このあたりは今後の検証課題ですね。

まとめ

今回はAmazon Bedrock AgentCoreのAgentCore Code Interpreterの感想や実際に動かしてみた記録をまとめてみました。
まだプレビューなのでSDKにちょっと癖がありますが、これだけ簡単にサンドボックス環境を準備できるのは革命ですね・・・!
エージェントに安定して安全なコードを生成させるには色々試行錯誤が必要ですが、そこも含めて試行錯誤しやすい環境が整いつつあると感じています。

次回はBrowser周りを触り倒していこうと思います。
続編をぜひお待ち頂ければと思います!