> 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.

# LangGraph

This guide shows how to integrate the AgentDuet SDK with [LangGraph](https://docs.langchain.com/oss/python/langgraph/overview) for durable agent workflows, including checkpointed state, human-in-the-loop interrupts, and policy-gated tools.

## What this integration provides

A voice agent that:

- Answers inbound calls and bridges 24 kHz PCM to Gemini Live
- Authenticates demo orders against a **local mock database** (no live store APIs)
- Speaks shipping status in one or two short sentences
- Allows address changes or cancellations only when fulfillment is `unfulfilled`

## How the pieces fit

```mermaid
flowchart LR
  Caller[Caller] --> AgentDuet[AgentDuet]
  AgentDuet --> Bridge[Gemini Live bridge]
  Bridge --> Gemini[Gemini Live]
  Bridge --> Graph[LangGraph OrderSession]
  Graph --> MockDB[Mock orders JSON]
```

| Layer | Owns |
|---|---|
| **AgentDuet** | Connector, inbound calls, PCM |
| **Gemini Live** | Speech-to-speech dialogue + tool calls |
| **LangGraph** | Call-scoped order state, tools, fulfillment policy |
| **Your app** | Prompts, mock orders, tool side effects |

PCM stays on the AgentDuet ↔ Gemini bridge. Graph checkpoints store compact business state only (order id, auth, fulfillment) — not audio.

## Prerequisites

- Python **3.12+**
- AgentDuet API key and connector UUID from [agentduet.com](https://agentduet.com)
- [Gemini API key](https://aistudio.google.com/apikey) for Gemini Live

## Step 1: Clone the sample

```bash
git clone https://github.com/AgentDuet/agentduet-samples.git
cd agentduet-samples/integrations/langgraph/order-tracking
```

Layout:

```
order-tracking/
├── main.py              # SessionManager + Gemini Live bridge
├── graph.py             # LangGraph OrderSession + tools
├── orders.py            # Mock DB helpers
├── prompts.py           # System prompt + greeting
├── data/orders.json     # Seed orders #1001 / #1002
├── requirements.txt
└── .env.example
```

## Step 2: Install dependencies

```bash
python3.12 -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -r requirements.txt
```

The sample pins [`agentduet==1.0.0`](https://pypi.org/project/agentduet/1.0.0/).

## Step 3: Configure `.env`

```bash
cp .env.example .env
```

```bash
AGENTDUET_API_KEY=your-connector-api-key
AGENTDUET_CONNECTOR_UUID=your-connector-uuid
GEMINI_API_KEY=your-gemini-api-key
```

## Step 4: Run locally

```bash
python main.py
```

Call your agent. It should answer and walk order status or a change/cancel.

### Demo orders

| Order | Zip | Fulfillment | Try |
|---|---|---|---|
| **#1001** | `94107` | `unfulfilled` | Spoken status; change address or cancel |
| **#1002** | `10001` | `fulfilled` | Spoken status; modifications declined |

Example scripts:

1. “Order 1001, zip 94107.” → short spoken status.
2. “Change my address to 88 Folsom Street, San Francisco, California, 94105.” → succeeds on #1001.
3. “Order 1002, zip 10001. Please cancel.” → status OK; cancel politely declined.

## Step 5: How LangGraph and AgentDuet connect

### SessionManager answers the call

From `main.py`:

```python
@sm.on_incoming_call
async def on_call(noti: IncomingCallNotification) -> None:
    session = await sm.open_session(new_session_id(), noti.subscriber)
    call = await session.process_call(noti)
    await handle_call(call)
```

### LangGraph owns tools and call state

From `graph.py`, each call builds an `OrderSession` with checkpointed `OrderState` (thread id = call id) and LangChain tools:

- `authenticate_order` — mock DB lookup by order id + zip
- `check_fulfillment_status` — policy gate before modifications
- `change_shipping_address` / `cancel_order` — allowed only when `unfulfilled`
- `hang_up` — end the call after the caller says goodbye

Gemini Live receives the tool declarations and dispatches through `OrderSession.ainvoke_tool`.

### Voice prompt rules

The system prompt in `prompts.py` instructs the agent to:

- Greet inbound callers and collect a test order id (`#1001` / `#1002`) plus zip
- Authenticate via the mock database tool (never invent status)
- Speak shipping status in one or two concise sentences
- Check fulfillment before modifications; decline politely when `fulfilled`
- Say a short goodbye and call `hang_up` when the caller is done
- Keep spoken replies short

## Notes

- Keep call control and PCM buffering on the AgentDuet path; put order policy in LangGraph tools.
- Map graph thread ids to stable conversation keys (this sample uses `call.id`).
- Restarting the process reloads seed orders from `data/orders.json`.
- This sample uses 24 kHz audio (`CallAudioConfig(sample_rate=24000)`).

## Related

- [Gemini Live](/integrations/gemini-live)
- [Google ADK](/integrations/google-adk)
- [Amazon Bedrock AgentCore](/integrations/amazon-bedrock-agent-core)
- [Order tracking sample on GitHub](https://github.com/AgentDuet/agentduet-samples/tree/main/integrations/langgraph/order-tracking)