> For the complete documentation index, see [llms.txt](https://docs.kyvvu.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kyvvu.com/integrations/langchain.md).

# LangChain / LangGraph

**What you'll learn:** How to instrument LangChain and LangGraph agents using the `KyvvuLangChainHandler` callback handler.

***

## Setup

The same handler works for both LangChain and LangGraph — LangGraph uses `langchain_core` callbacks under the hood.

```python
from kyvvu import Kyvvu
from kyvvu.schemas import Environment, RiskClassification
from kyvvu.integrations.langchain import KyvvuLangChainHandler

kv = Kyvvu(
    api_key="KvKey-...",
    api_url="https://platform.kyvvu.com",
    agent_key="finance-agent",
    environment=Environment.DEVELOPMENT,
    risk_classification=RiskClassification.LIMITED,
)
kv.register_agent(
    name="Finance Agent",
    purpose="Stock ticker lookup and portfolio analysis for internal use",
    metadata={"framework": "langchain", "tools": ["search"]},
)

handler = KyvvuLangChainHandler(kv)
result = agent.invoke(query, config={"callbacks": [handler]})
```

The handler is a pure adapter. It doesn't manage identity or registration — the same `Kyvvu()` + `register_agent()` pattern as the decorator integration.

## Callback event mapping

The handler translates LangChain callback events to Kyvvu Behaviors:

| LangChain callback                     | Kyvvu step\_type | Verb   | Notes                            |
| -------------------------------------- | ---------------- | ------ | -------------------------------- |
| `on_llm_start` / `on_chat_model_start` | `step.model`     | `POST` | Model name extracted from kwargs |
| `on_tool_start`                        | `step.resource`  | `POST` | Tool name becomes `step_name`    |
| `on_chain_start`                       | `step.self`      | `POST` | Chain/graph node entry           |
| `on_chain_end`                         | `step.self`      | `GET`  | Chain/graph node exit            |
| `on_retriever_start`                   | `step.resource`  | `GET`  | Retrieval step                   |

Each event goes through the template system. The built-in `langchain` template defines these mappings. Custom templates can override them.

## Nested chain resolution

LangChain/LangGraph agents often produce deeply nested chain callbacks. The handler resolves nested chains to keep the behavioral trace readable:

* Top-level chain events produce Behaviors.
* Deeply nested internal chains are collapsed unless they represent distinct logical steps.
* Tool calls within chains are always surfaced.

## Block propagation

When a policy blocks a step during a LangChain callback:

1. The handler receives the `KyvvuBlockedError`.
2. With `raise_error=True` (default), the error propagates up through the LangChain callback chain, halting execution.
3. The agent code can catch `KyvvuBlockedError` at the top level.

```python
from kyvvu import KyvvuBlockedError

handler = KyvvuLangChainHandler(kv)
try:
    result = agent.invoke(query, config={"callbacks": [handler]})
except KyvvuBlockedError as exc:
    print(f"Policy blocked: {exc}")
```

## Task lifecycle

The handler automatically manages task lifecycle:

* A task starts on the first callback event.
* The task ends when the top-level chain completes.
* If the chain raises an exception, `error_task()` is called.

## Custom templates for LangChain

To add custom property mappings:

```python
from kyvvu_engine.templates import BehaviorTemplate

template = BehaviorTemplate.from_path("my_langchain_template.yaml")
kv = Kyvvu(api_key="...", agent_key="bot", template=template)
handler = KyvvuLangChainHandler(kv)
```

The custom template can map specific tool names to detailed properties (target system, data classification, etc.) while falling back to the built-in langchain template for unmatched events.

## LangGraph-specific notes

LangGraph agents use the same handler. Pass via `config`:

```python
from langgraph.graph import StateGraph

graph = StateGraph(...)
# ... build graph ...
app = graph.compile()

handler = KyvvuLangChainHandler(kv)
result = app.invoke(input_data, config={"callbacks": [handler]})
```

Graph node transitions appear as `step.self` events in the behavioral trace. Tool calls within nodes appear as `step.resource` events.

### Dedicated LangGraph handler

For richer graph-aware tracing, use `KyvvuLangGraphHandler` (`kyvvu.integrations.langgraph`), a subclass of `KyvvuLangChainHandler` that adds two things:

* **Node metadata** — injects `properties.langgraph.node_name` from the callback metadata, so the trace records which graph node each step ran in.
* **Interrupt mapping** — maps LangGraph's `GraphInterrupt` (raised by `interrupt()`) to a `step.gate` behavior, so human-in-the-loop breakpoints are governable by gate policies.

```python
from kyvvu.integrations.langgraph import KyvvuLangGraphHandler

handler = KyvvuLangGraphHandler(kv)
result = app.invoke(input_data, config={"callbacks": [handler]})
```

The shared `KyvvuLangChainHandler` still works for LangGraph; the dedicated handler is opt-in when you want node metadata or HITL gate mapping.

### Parallel tool calls within a step

When the LLM emits multiple `tool_use` blocks and the runtime dispatches them concurrently (e.g., `asyncio.gather` in LangGraph), Kyvvu sees N sibling tool calls under the same parent `run_id`. The behavioral trace timestamps them in completion order, not invocation order.

**Path policies operate across steps, not within them.** A policy like "must call X before Y" is well-defined when X and Y are in different steps (X in step 1, Y in step 2). It is ill-defined when X and Y are dispatched concurrently within the same step — their ordering is non-deterministic. Policy authors should specify ordering constraints across steps, not between parallel calls within one.

**Kyvvu evaluates the path; it does not serialise the dispatcher.** If a policy requires sequential execution, the developer must enforce it in the runtime — sequential awaits, or a single-tool-per-step constraint in the agent prompt. Kyvvu records what happened; it does not control dispatch order.

***

## Integration status

| Framework                 | Status    | Notes                                                                                                                    |
| ------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------ |
| LangChain                 | Available | Full support via `KyvvuLangChainHandler`.                                                                                |
| LangGraph                 | Available | Shared `KyvvuLangChainHandler`, or `KyvvuLangGraphHandler` for node metadata and `GraphInterrupt` → `step.gate` mapping. |
| CrewAI                    | Available | Native support via `KyvvuCrewAIListener` (`kyvvu.integrations.crewai`), wired to the CrewAI event bus.                   |
| Microsoft AutoGen         | Planned   | Native adapter in development.                                                                                           |
| Microsoft Semantic Kernel | Planned   | Native adapter in development.                                                                                           |

Interested in a framework not listed here? Contact us at <support@kyvvu.com>.

***

## Next steps

* [Python Decorator](/integrations/decorator.md) — alternative integration for custom Python agents
* [Writing a New Integration](/integrations/custom.md) — build a handler for another framework
* [Templates](/core-concepts/templates.md) — customize the event-to-Behavior mapping


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.kyvvu.com/integrations/langchain.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
