AWS での AI エージェント開発を 2 倍速にする Inline Agent SDK

2025 年は AI エージェント元年とも呼ばれ、日々アップデートされる技術の検証に忙しい方も多いと思います。AWS では [Amazon Bedrock Agent](https://aws.amazon.com/jp/bedrock/agents/) を利用して AI エージェントの開発が出来ます。出来ますが・・・が、仕様の変更頻度が高い状況では Lambda の事前デプロイやバージョン管理などが手間になっていました。

[**Amazon Bedrock Inline Agent SDK**](https://github.com/awslabs/amazon-bedrock-agent-samples/tree/main/src/InlineAgent) は AWS から実験的に公開されている SDK で開発の速度に重点を置いています。[Langfuse](https://langfuse.com/) や [Phoenix](https://phoenix.arize.com/) と連携した Observability の強化や [Model Context Protcol](https://www.anthropic.com/news/model-context-protocol) (MCP) を通じた外部ツールとの連携も実装されています。

本記事では、AWS での実験速度のギアを一段上げてくれる Inline Agent SDK の特徴と使用方法を解説します。

```plantuml
@startuml
<style>
root {
  Padding 0
  Margin 10
}
footer {
  FontColor black
  FontSize 24
}
</style>
footer Amazon Nova Canvas で作成した 2 倍速で疾走するにゃんこ
title <img:https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25990/752eaaa5-215b-4740-be1a-3a741a301881.png>
@enduml
```

## 従来の Amazon Bedrock Agent と Inline Agent SDK の違い

なぜ Inline Agent SDK を使うと開発速度が 2 倍になるのか ? まず、Amazon Bedrock Agent で AI エージェントを開発する際は、次の 7 ステップを踏む必要がありました (参考 : [Create Agent with Function Definition](https://aws-samples.github.io/amazon-bedrock-samples/agents-and-function-calling/bedrock-agents/features-examples/01-create-agent-with-function-definition/01-create-agent-with-function-definition/))。

1. Tool として呼び出す関数の実装
2. 関数を AWS Lambda としてデプロイ (必要に応じ呼び出し用の IAM Role / Policy も作成)
3. エージェントにとっての Tool となる [ActionGroup](https://docs.aws.amazon.com/bedrock/latest/userguide/agents-action-function.html) を `functionSchema` (もしくは Open API Schema ベースの `API Schema`) と Lambda の Arn から作成
4. (必要に応じナレッジの検索する Knowledge Bases を使用)
5. Agent を実装 (必要に応じ呼び出し用の IAM Role / Policy も作成)
6. 呼び出す前に Prepare でバージョンを更新
7. エージェントを実行
 
この手順を見てため息が出た方もいるかもしれません。一方で、仕様が決まっていれば CloudFormation や CDK で一気に構築でき、構築後は必要十分な権限による安全な実行とバックエンドのスケーラビリティが享受できます。ただ、試行錯誤の実験段階でその優先度は低いでしょう。

[Inline Agent](https://docs.aws.amazon.com/bedrock/latest/userguide/inline-agent-invoke.html) とそれを利用した [Inline Agent SDK](https://github.com/awslabs/amazon-bedrock-agent-samples/tree/main/src/InlineAgent) により手順を 3 ステップ、2 倍超に短縮できます。内訳は次の通りです。

| ステップ | 従来の Amazon Bedrock Agent | Inline Agent SDK |
|---------|---------------------------|-----------------|
| 1 | Tool として呼び出す関数の実装 | Tool として呼び出す関数の実装 |
| 2 | 関数を AWS Lambda としてデプロイ<br>(IAM Role/Policy も作成) | **不要**<br>(ローカル関数として実行可能) |
| 3 | ActionGroup を `functionSchema` と<br>Lambda の Arn から作成 | **不要**<br>(docstring から自動的にSchema定義) |
| 4 | Knowledge Bases の作成<br>(必要に応じて) | Knowledge Bases の作成<br>(必要に応じて) |
| 5 | Agent を実装<br>(IAM Role/Policy も作成) | Agent を実装 |
| 6 | Prepare でバージョンを更新 | **不要** <br>(ActionGroup/Knowledge Bases の<br>動的割り当てが可能) |
| 7 | エージェントを実行 | エージェントを実行 |

ポイントは次の通りです。

* Step 2: Inline Agent SDK により、Tool の実行を AWS 上の Lambda から呼び出し元 (ローカル) へ引き戻す [Return Control](https://docs.aws.amazon.com/bedrock/latest/userguide/agents-returncontrol.html) の利用が容易に
* Step 3: Inline Agent SDK により、docstring を書いておけばそれを Schema 定義に使用
* Step 6: Inline Agent の仕様により ActionGroup/Knowledge Bases の動的な割り当てが可能に (事前発行が不要)

実際の実装を見てみましょう。 `ActionGroup` は定義する必要がありますが、簡単に作成できます (下記実装では、`agent` の定義内で行っています)。

```py
import asyncio
import random
from InlineAgent.action_group import ActionGroup
from InlineAgent.agent import InlineAgent

# 1. Define a tool as a Python function with docstring
def get_weather(location: str, state: str) -> dict:
    """
    Get the current weather in a given location.

    Parameters:
        location: The city, e.g., San Francisco
        state: The state eg CA
    """
    weather_candidates = [
        'Sunny', 
        'Cloudy', 
        'Rainy', 
    ]
    random_weather = random.choice(weather_candidates)    

    return f"Weather at {location} {state} is {random_weather}."

# 2. Configure the agent with ActionGroup
agent = InlineAgent(
    agent_name="WeatherAgent",
    foundation_model="us.anthropic.claude-3-5-haiku-20241022-v1:0",
    instruction="You are a friendly assistant that is responsible for getting the current weather.",
    action_groups=[
        ActionGroup(
            name="WeatherTools",
            description="Tools for weather information",
            tools=[get_weather]
        )
    ],
)

# 3. Invoke the agent
response = asyncio.run(agent.invoke(
    input_text="What's the weather in Tokyo Shinagawa-ku?"
))

```

とてもシンプルに書けます。シンプルに書くなら今まで使っている LangChain / LangGraph で、という方はそれでも OK で、OSS のフレームワークを使いつつ面倒なセッション管理などのみ AWS へ委譲できる [Amazon Bedrock Session Management Service](https://github.com/langchain-ai/langchain-aws/tree/main/libs/langgraph-checkpoint-aws) が提供されています。まだフレームワークとかを特に使っていなくて、AWS で実装したいと考えているが 7 ステップは面倒すぎると感じる方は次の Inline Agent SDK からぜひお試しください。

## Inline Agent SDK の導入

Inline Agent SDK のセットアップ手順は [Amazon Bedrock Inline Agent SDK ](https://github.com/awslabs/amazon-bedrock-agent-samples/tree/main/src/InlineAgent) にまとめられています。注意点として、Python 3.11 以上が必要です。比較的新しいバージョンなので、ローカルの Python バージョンが低い場合 [`uv`](https://github.com/astral-sh/uv) を使うと簡単にセットアップできます。

```
git clone https://github.com/awslabs/amazon-bedrock-agent-samples.git
cd amazon-bedrock-agent-samples/src/InlineAgent
uv sync
uv pip install -e .
# 動作確認
aws configure  # AWS への接続を確認
uv run InlineAgent_hello us.anthropic.claude-3-5-haiku-20241022-v1:0
```

Running Hellow world agent がエラーなく実行されたらインストールは完了です。下記に私が実行した時のログを参考に示します。

> Input Tokens: 600 Output Tokens: 137
Thought: The user has greeted me and asked about my capabilities. I'll respond in a friendly manner and use the user interaction tool to engage with them.
Hello there! I'm doing great, thank you for asking. I'm a friendly assistant who loves to say hello to everything! What would you like help with today? I'm ready to assist you with any questions or tasks you might have.
Agent made a total of 1 LLM calls, using 737 tokens (in: 600, out: 137), and took 4.6 total seconds

## Inline Agent SDK : 4 つの主要機能

Inline Agent SDKには、開発を加速する4つの主要機能があります。これらを組み合わせることで、高速な AI エージェントの検証ができます。

### 1. ローカル関数を Tool として使用

従来の Agent では、Tool を Lambda 関数として実装する必要がありましたが、Inline Agent SDK では先ほどの Return Control の仕組みによりローカルの Python 関数をそのまま使用できます。関数の定義や docstring から自動的に Function Schema が生成されるため、手動で定義する手間が省けます。

```python
# docstring を持つPython関数をツールとして定義
def get_weather(location: str, unit: str = "fahrenheit") -> str:
    """Get current weather for a location."""
    return f"Weather in {location} is sunny and 72 degrees {unit}"

# アクショングループを作成
weather_group = ActionGroup(
    name="WeatherTools",
    description="Tools for weather information",
    tools=[get_weather]
)
```
Inline Agent SDK で隠蔽されている Return of Control (RoC) の処理プロセスが気になる方のために呼び出しのフローを解説します。

**User** によって `input_text` が送られると AWS 上の **Inline Agent** が **Foundation Model** を使用して呼び出しが必要なツールを特定します。この後は通常 AWS Lambda が呼ばれますが、[ActionGroup 作成時に `actionGroupExecutor` として 'RETURN_CONTROL' を設定しておくと](https://aws-samples.github.io/amazon-bedrock-samples/agents-and-function-calling/bedrock-agents/features-examples/03-create-agent-with-return-of-control/03-create-agent-with-return-of-control/) 実行に必要な情報 (特定された Tool 、Paramter ) が呼び出し元に戻されます。Inline Agent SDK では **ProcessROC** クラスが戻された内容を基に **Local Function** を実行し実行結果を **Inline Agent** に戻しています。**Inline Agent** は受け取った結果を **Foundation Model** に渡し response を得て *User* に返却します。


```mermaid
sequenceDiagram
    participant User
    participant Agent as Inline Agent
    participant LLM as Foundation Model
    participant RoC as ProcessROC
    participant Function as Local Function

    User->>Agent: invoke(input_text)
    Agent->>LLM: Send user query
    LLM-->>Agent: Return Control event
    Agent->>RoC: process_roc()
    RoC->>RoC: Extract parameters
    RoC->>Function: Execute function
    Function-->>RoC: Return result
    RoC-->>Agent: Format result
    Agent->>LLM: Continue with result
    LLM-->>Agent: Final response
    Agent-->>User: Formatted response
```

### 2. ナレッジベース統合

従来の Amazon Bedrock Agent では、エージェントに Knowledge Base の ID を紐付ける必要がありますが、Inline Agent SDK では Tool と同様に名称と記述で関連付けることが出来ます。

```python
agent = InlineAgent(
    foundation_model="us.anthropic.claude-3-5-haiku-20241022-v1:0",
    knowledge_bases=[
        KnowledgeBasePlugin(name="product-kb", description="製品情報")
    ]
)
```

ナレッジベースは複数登録できるため、製品カタログと顧客応対マニュアルなど、異なる種類の情報を持つ複数のナレッジベースをクエリに応じて切り替えられます。

```python
agent = InlineAgent(
    knowledge_bases=[
        KnowledgeBasePlugin(name="technical-docs"),
        KnowledgeBasePlugin(name="product-catalog")
    ]
)
```

### 3. 可観測性（Observability）

Inline Agent SDK ではエージェントの動作をトレースしデバッグ・監視するため機能が提供されています。Langfuse や Phoenix といった LLM アプリケーションの監視ツールとも機能統合が出来ます。

```python
@observe(show_traces=True)
def invoke_agent(input_text, session_id):
    # エージェント呼び出しコード
```

`observe` のデコレーターにより、以下のような情報を収集できます：

- Token Usage : 入出力トークン数
- LLM Calls : LLM呼び出しとそのパラメータ
- Tool Usage : ツール呼び出しとレスポンス
- Execution Time : 各コンポーネントの実行時間

```mermaid
flowchart TD
    A[Agent Invocation] --> B[Trace Collection]
    B --> C{Observability Tools}
    C --> D[Langfuse]
    C --> E[Phoenix]
    C --> F[Console Output]
    
    D --> G[Performance Analysis]
    E --> G
    F --> G
    
    subgraph "Metrics Collected"
    H[Token Usage]
    I[Execution Time]
    J[LLM Calls]
    K[Tool Usage]
    end
    
    B --> H
    B --> I
    B --> J
    B --> K
```

### 4. 外部ツール統合

Model Context Protocol (MCP)サーバー、[CrewAI Toolkit](https://github.com/crewAIInc/crewAI-tools)、[Langchain Tools](https://python.langchain.com/docs/integrations/tools/) などの外部ツールと簡単に接続できます：

```python
time_mcp_client = await MCPStdio.create(server_params=server_params)
time_action_group = ActionGroup(
    name="TimeTools",
    mcp_clients=[time_mcp_client]
)
```

`MCPStdio` は MCPServer を作成するためのラッパーで、[Model Context Protocol servers](https://github.com/modelcontextprotocol/servers) で定義されている `StdioServerParameters` を受け取り特定の MCP サーバーに接続するための Transport (Stdio を利用) レイヤの接続と Session の接続・初期化を行っています。 MCP サーバーに登録されている Tool の情報から Amazon Bedrock Agent が呼び出せる functionSchema を作成する作業も Inline Agent の中で行われているので、上記のように ActionGroup の定義で直接 MCP Client を入力できます。

外部ツールと内部ツールは排他的でないため、次のように双方を呼び出し対象として登録できます。

```python
agent = InlineAgent(
    action_groups=[
        ActionGroup(name="LocalTools", tools=[local_function1, local_function2]),
        ActionGroup(name="ExternalTools", mcp_clients=[mcp_client])
    ]
)
```

例えば、社内データベースへのアクセスはローカル関数で、検索機能は外部ツールで実装するといった使い方ができます。

## Inline Agent SDK と従来の Amazon Bedrock Agent の使い分け

Inline Agent SDK は初期の実験、Amazon Bedrock Agent は実装が固まった後のスケールに適しているので、仕様が固まった、本格的に利用が増えてきたタイミングで AWS Lambda の構築やバージョン管理を行う後者への移行をお勧めします。そもそも、Inline Agent SDK は記事執筆時点ではサンプルの中の一部でありパッケージとして独立していないので、開発ステータス的にも実験段階で使うのが適切と思います。

Inline Agent SDK が適しているパターン :
- 迅速なプロトタイピング：アイデアを素早く試し、フィードバックを得たい場合
- ローカル開発での開発：クラウドリソースのセットアップなしで開発したい場合
- 外部エコシステムとの統合：MCP や CrewAI、Langchain など様々なツールを使いたい場合
- 詳細なデバッグ情報が必要：エージェントの動作を細かく分析したい場合

一方、従来のAgentは以下のような場合に適しています

- 厳格なガバナンスを持つ本番環境へのデプロイ
- エンタープライズグレードのスケーリングが必要
- 複雑なセキュリティポリシーの実装
- 実装をパターン化し横展開したい

## おわりに

本記事では、AWS での AI エージェント開発を効率化する Inline Agent SDK のメリット・機能・使いどころをご紹介しました。今後、正式なパッケージとなってくれることを期待です！