> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.agentduet.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.agentduet.com/_mcp/server.

# Amazon Bedrock AgentCore

This guide shows how to integrate the AgentDuet SDK with [Amazon Bedrock AgentCore](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/what-is-bedrock-agentcore.html) for hosted agent runtimes with lifecycle management, memory, governed tools, and observability around live phone agents.

This guide uses the **FinAssist** sample from [agentduet-samples](https://github.com/AgentDuet/agentduet-samples/tree/main/integrations/bedrock-agentcore/finassist). Speech uses [Amazon Nova Sonic](/integrations/amazon-nova-sonic) over Bedrock.

## What this integration provides

A voice agent that:

- Starts an AgentDuet listener when the AgentCore runtime comes up
- Answers inbound calls and bridges 24 kHz PCM to Nova Sonic 2
- Keeps eligibility / tool-style actions reachable over AgentCore `invoke`
- Can deploy the same app to AWS with `agentcore deploy`

Demo domain: **SecureFinance** loans and insurance claims over the phone.

## How the pieces fit

```mermaid
flowchart TB
  Caller((Caller))

  subgraph Runtime["Amazon Bedrock AgentCore runtime"]
    direction LR
    AD["AgentDuet<br/>answer + PCM bridge"]
    Nova["Amazon Nova Sonic 2<br/>speech-to-speech"]
    Rules["Loan / claim rules"]
    AD <-->|"audio in / spoken reply"| Nova
    Nova -.-> Rules
  end

  Caller <-->|"caller audio / reply audio"| AD
  Invoke["agentcore invoke / ping"] -.-> Runtime
```

| Layer | Owns |
|---|---|
| **AgentCore** | Process host, lifespan, health (`ping`), `entrypoint` invoke |
| **AgentDuet** | Connector, inbound calls, `answer` / `send_audio` / barge-in |
| **Nova Sonic** | Speech-to-speech stream on Bedrock |
| **Your app** | Prompts, eligibility rules, optional transcript upload |

For a Nova-only bridge without AgentCore, see [Amazon Nova Sonic](/integrations/amazon-nova-sonic).

## Prerequisites

- Python **3.12+**
- Node.js **20+** and the [`@aws/agentcore`](https://www.npmjs.com/package/@aws/agentcore) CLI
- AWS credentials with Bedrock access (SSO recommended)
- AgentDuet API key and connector UUID from [agentduet.com](https://agentduet.com)
- `uv` for the app virtualenv

Deploy also needs an IAM role with CloudFormation + AgentCore permissions (Bedrock-only access is not enough).

## Step 1: Clone the sample

```bash
git clone https://github.com/AgentDuet/agentduet-samples.git
cd agentduet-samples/integrations/bedrock-agentcore/finassist
```

Layout:

```
finassist/
├── agentcore/          # agentcore.json, AWS targets, local secrets
└── app/
    ├── main.py         # AgentCore entrypoint + lifespan
    ├── pyproject.toml
    └── finassist_agent/
        ├── voice_service.py   # AgentDuet SessionManager + call bridge
        ├── nova_sonic.py      # Bedrock bidirectional stream
        ├── prompts.py
        └── logic.py           # Loan / claim rules
```

Full source: [agentduet-samples / bedrock-agentcore / finassist](https://github.com/AgentDuet/agentduet-samples/tree/main/integrations/bedrock-agentcore/finassist).

## Step 2: Install CLI and app deps

```bash
npm install -g @aws/agentcore
cd agentcore/cdk && npm install && cd ../..
cd app && uv sync --python 3.12 && cd ..
```

## Step 3: Configure credentials

```bash
cp agentcore/aws-targets.json.example agentcore/aws-targets.json
cp agentcore/.env.local.example agentcore/.env.local
```

1. Set your 12-digit AWS account ID in `agentcore/aws-targets.json`.
2. Fill AgentDuet secrets in `agentcore/.env.local`:

```bash
AGENTDUET_API_KEY=your-connector-api-key
AGENTDUET_CONNECTOR_UUID=your-connector-uuid
AWS_DEFAULT_REGION=ap-southeast-1
NOVA_SONIC_REGION=ap-northeast-1
NOVA_SONIC_MODEL_ID=amazon.nova-2-sonic-v1:0
NOVA_SONIC_VOICE_ID=matthew
```

3. Authenticate AWS in the shell (do not commit access keys):

```bash
export AWS_PROFILE=your-sso-profile
aws sso login --profile your-sso-profile
aws sts get-caller-identity
```

`.env.local` is for local `agentcore dev` only. Cloud deploy reads env from `agentcore.json` (see Step 6).

## Step 4: Run locally

```bash
agentcore dev
```

Call your AgentDuet connector number. FinAssist should answer as SecureFinance and walk loan or claim intake.

Optional HTTP-style checks against the same process:

```bash
agentcore dev '{"action": "status"}'
agentcore dev '{"action": "evaluate_loan", "amount": 15000, "annual_income": 60000, "purpose": "home repair"}'
```

## Step 5: How AgentCore starts AgentDuet

AgentCore lifespan starts the voice listener. AgentDuet does not own process signals.

### Lifespan starts the voice listener

From `app/main.py`:

```python
@asynccontextmanager
async def lifespan(app: BedrockAgentCoreApp):
    """Start AgentDuet voice listener when AgentCore starts."""
    _listener_task_id = app.add_async_task(
        "agentduet_nova_listener",
        {"connector": os.getenv("AGENTDUET_CONNECTOR_UUID", "")},
    )
    _listener_task = asyncio.create_task(voice_service.run_forever())
    yield
    voice_service.request_shutdown()
    # cancel listener task, complete_async_task ...

app = BedrockAgentCoreApp(lifespan=lifespan)
```

### SessionManager runs under AgentCore

From `app/finassist_agent/voice_service.py`:

```python
# install_signal_handlers=False: AgentCore owns process signals / lifespan.
async with SessionManager(config) as sm:
    @sm.on_incoming_call
    async def on_call(noti: IncomingCallNotification) -> None:
        await self.handle_incoming_call(sm, noti)

    await sm.run_forever(install_signal_handlers=False)
```

On shutdown, `request_shutdown()` disconnects the SessionManager so `run_forever` exits cleanly.

### Invoke and live audio

`@app.entrypoint` handles `status`, `evaluate_loan`, and `evaluate_claim`. Live calls go through AgentDuet events and the Nova bridge.

## Step 6: Deploy to AWS

Set `AGENTDUET_API_KEY` and `AGENTDUET_CONNECTOR_UUID` in `agentcore/agentcore.json` `envVars` (placeholders ship in the sample). Then:

```bash
agentcore deploy
agentcore invoke '{"action": "status"}'
agentcore logs
```

## Notes

- Keep call control and PCM buffering on the AgentDuet path; use invoke for structured actions only.
- Treat call id, customer identity, and AgentCore `context.session_id` as separate namespaces.
- This sample uses 24 kHz audio (`CallAudioConfig(sample_rate=24000)`).
- Runtime region and Nova model region can differ (`AWS_DEFAULT_REGION` vs `NOVA_SONIC_REGION`).
- Optional transcript upload when `TRANSCRIPT_S3_BUCKET` is set.

## Related

- [Amazon Nova Sonic](/integrations/amazon-nova-sonic)
- [Audio Streaming](/concepts/audio-streaming)
- [Call States and Lifecycle](/concepts/call-states-and-lifecycle)
- [FinAssist sample on GitHub](https://github.com/AgentDuet/agentduet-samples/tree/main/integrations/bedrock-agentcore/finassist)