Skip to navigation

LangGraph

View as Markdown

This guide shows how to integrate the AgentDuet SDK with LangGraph 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

Caller AgentDuet Gemini Live bridge Gemini Live LangGraph OrderSession Mock orders JSON
LayerOwns
AgentDuetConnector, inbound calls, PCM
Gemini LiveSpeech-to-speech dialogue + tool calls
LangGraphCall-scoped order state, tools, fulfillment policy
Your appPrompts, 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

Step 1: Clone the sample

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

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.

Step 3: Configure .env

cp .env.example .env
AGENTDUET_API_KEY=your-connector-api-key
AGENTDUET_CONNECTOR_UUID=your-connector-uuid
GEMINI_API_KEY=your-gemini-api-key

Step 4: Run locally

python main.py

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

Demo orders

OrderZipFulfillmentTry
#100194107unfulfilledSpoken status; change address or cancel
#100210001fulfilledSpoken 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:

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

Next Step