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

### 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 observes 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\~ | Works via the LangChain callback handler. Dedicated adapter with richer graph-aware tracing planned. |
| CrewAI                    | Planned     | Native adapter in development.                                                                       |
| 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: 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:

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

The question should be specific, self-contained, and written in natural language.
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.
