> ## Documentation Index
> Fetch the complete documentation index at: https://docs.waterr.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# LangChain

> Put your LangChain/LangGraph agent on a real-time video call as the persona — and let it create scenarios, dispatch meetings, and act on the results.

You've already built a LangChain or LangGraph agent: a graph with a model,
tools, memory, and guardrails. On Waterr, that agent can play **two roles**:

1. **The agent IS the persona** — it joins a live video meeting as the AI
   character: it hears the participant, thinks with *your* graph, and speaks
   the reply. Waterr supplies the face, voice, ears, and room; your agent
   supplies the mind.
2. **The agent operates the platform** — using the
   [`langchain-waterr`](https://github.com/waterrai/langchain-waterr) toolkit
   it creates personas, defines scenarios on the fly, dispatches meetings,
   and reads back goal-scored results.

Most real builds use both: the agent sets up the meeting *and* takes it.
This page walks through each role, then closes the loop.

```bash theme={null}
pip install "git+https://github.com/waterrai/langchain-waterr"
export WATERR_API_KEY="wai_..."   # waterr.ai/settings?tab=api-keys
```

## Role 1 — Your agent as the meeting persona

This is the part that usually surprises people: you don't port your agent
into a new SDK. Waterr's meeting pipeline speaks the OpenAI chat-completions
protocol to whatever endpoint a scenario points at
([Bring Your Own Agent](/api-reference/bring-your-own-agent)). Serve your
graph behind that shape and it becomes the voice on the call.

### Step 1 — Wrap your graph in an OpenAI-compatible endpoint

LangGraph's `astream` (with `stream_mode="messages"`) yields exactly what an
SSE chat-completions response needs:

```python theme={null}
# pip install fastapi uvicorn langgraph
import json, time
from fastapi import FastAPI, Request
from fastapi.responses import StreamingResponse
from langgraph.prebuilt import create_react_agent

graph = create_react_agent(model, tools=my_tools)   # your existing agent

app = FastAPI()

@app.post("/v1/chat/completions")
async def chat(request: Request):
    body = await request.json()
    # body["messages"] is the running meeting conversation — Waterr's system
    # prompt (the scenario script) first, then alternating user/assistant
    # turns transcribed from the live call.

    async def sse():
        async for token, _meta in graph.astream(
            {"messages": body["messages"]}, stream_mode="messages"
        ):
            if token.content:
                chunk = {
                    "id": "chatcmpl-waterr",
                    "object": "chat.completion.chunk",
                    "created": int(time.time()),
                    "model": body.get("model"),
                    "choices": [{"index": 0,
                                 "delta": {"content": token.content},
                                 "finish_reason": None}],
                }
                yield f"data: {json.dumps(chunk)}\n\n"
        yield 'data: {"choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}\n\n'
        yield "data: [DONE]\n\n"

    return StreamingResponse(sse(), media_type="text/event-stream")
```

Your tools (CRM lookups, order status, ticketing) run inside the graph as
they always have — server-side, invisible to Waterr, no registration needed.

### Step 2 — Point a scenario at it

```bash theme={null}
curl -X PUT https://api.waterr.ai/v1/scenarios/{scenario_id} \
  -H "Authorization: Bearer wai_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "custom_agent_enabled": true,
    "custom_agent_config": {
      "base_url": "https://agent.yourcompany.com/v1",
      "api_key": "sk-your-endpoint-key",
      "model": "screening-agent-v2"
    }
  }'
```

### Step 3 — That's it

Every meeting on that scenario now runs on your graph. The participant sees a
persona in a video room; under the hood Waterr transcribes them in real time,
POSTs the conversation to your endpoint, and speaks your streamed tokens back
— with turn-taking, interruptions, transcripts, and analysis all handled.

<Note>
  Keep first-token latency under \~1.5s — this is a live conversation, and slow
  graphs feel slow even with Waterr's filler-audio masking. Endpoint contract,
  security model, and timeout behavior are on the
  [Bring Your Own Agent](/api-reference/bring-your-own-agent) page.
</Note>

## Role 2 — Your agent as the operator

The `WaterrToolkit` gives your agent five tools to run the platform itself:

| Tool | What the agent does with it |
| - | - |
| `waterr_create_persona` | Invent the character: name, job title, demeanor, background |
| `waterr_create_scenario` | Define the meeting dynamically: script, persona, goals to score against |
| `waterr_list_scenarios` | Reuse what already exists instead of recreating it |
| `waterr_create_meeting` | Dispatch a live meeting and get the join URL to hand to the human |
| `waterr_get_meeting_results` | Read status, summary, per-goal scores, strengths/growth areas, transcript |

```python theme={null}
from langchain_waterr import WaterrToolkit
from langgraph.prebuilt import create_react_agent

agent = create_react_agent(model, WaterrToolkit().get_tools())
```

The interesting part is **dynamic scenario creation**: because scenarios are
just API objects, your agent can compose a bespoke interview/discovery/
training session per situation — persona and script generated from context it
already has (a job description, a support ticket, a CRM record) — rather than
picking from a fixed menu:

```python theme={null}
agent.invoke({"messages": [(
    "user",
    "Here's the JD for our Staff Backend role. Create an interviewer persona "
    "that fits our culture doc, build a 30-minute screening scenario with "
    "goals for distributed-systems depth and communication, then create a "
    "meeting for Ada Lovelace and give me her join link."
)]})
```

The agent chains `waterr_create_persona` → `waterr_create_scenario` →
`waterr_create_meeting` and returns a URL. Ada clicks it, has the interview
in the browser, and afterwards the same agent calls
`waterr_get_meeting_results` to score her against the goals and decide the
next step — advance, reject, or schedule round two.

## The full loop

Combine the roles and the whole system is yours end to end:

1. **Operator**: your agent generates the persona + scenario and creates the
   meeting (toolkit).
2. **Persona**: the meeting's brain is your graph via the connector — same
   memory and tools that created it.
3. **Feedback**: [webhooks](/api-reference/webhooks) (`transcript.ready`,
   `session.analysis_complete`) push the transcript and analysis back into
   your pipeline, where the agent acts on the outcome.

Waterr is the face and the room; your LangGraph is the mind and the memory —
before, during, and after the call.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.