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

# LangGraph

> Deploy a compiled LangGraph graph as it is: streamed tokens, tool calls, tool results and each node as a step.

## What is supported

LangGraph 1.0 and later. Onecortex recognises a **compiled** graph: the result of `StateGraph(...).compile()`, and anything that returns one, such as LangChain's `create_agent`. An uncompiled `StateGraph` is not recognised.

## A complete agent

```yaml agent.yml theme={null}
apiVersion: v1
runtime: python3.12
entrypoint: agent.py:graph
dependencies: requirements.txt
```

```text requirements.txt theme={null}
langgraph>=1.0
langchain>=1.0
langchain-openai>=1.0
```

```python agent.py theme={null}
from langchain.chat_models import init_chat_model
from langchain_core.runnables import RunnableConfig
from langgraph.graph import START, MessagesState, StateGraph

# Reads OPENAI_API_KEY, which you add as a secret on the agent's Config tab.
model = init_chat_model("openai:gpt-5")


def respond(state: MessagesState, config: RunnableConfig) -> dict:
    return {"messages": [model.invoke(state["messages"])]}


builder = StateGraph(MessagesState)
builder.add_node("respond", respond)
builder.add_edge(START, "respond")
graph = builder.compile()
```

Add `OPENAI_API_KEY` as a secret on the agent's **Config** tab, then deploy. Any model works: this one is an example. See [Configuration and secrets](/build/configuration).

<Card title="A complete LangGraph example" icon="github" href="https://github.com/onecortex-io/examples/tree/main/support-triage">
  `support-triage`: A support graph with a tool node and a checkpointer, on the oldest supported LangGraph. It runs with no model key.
</Card>

## The prompt and the reply

The prompt arrives as the graph's input state, `{"messages": [{"role": "user", "content": prompt}]}`, so a graph on `MessagesState` works unchanged. The reply is the text of the last message. A graph whose state has no `messages` answers with its final state as text.

## Events it reports

| Events | From |
| - | - |
| `text` | The model's streamed tokens |
| `tool_call_start`, `tool_call_args`, `tool_call_end` | Each tool call the model makes, as it forms |
| `tool_result` | Each tool's reply, with `isError` when the tool failed |
| `step_start`, `step_end` | Each node, by its name |
| `done` or `error` | The end of the run: always exactly one |

See [Streaming and events](/build/streaming).

## The caller's fields

Under `config["configurable"]["onecortex"]`, in any node that takes a `config` argument:

```python theme={null}
def respond(state: MessagesState, config: RunnableConfig) -> dict:
    params = config["configurable"]["onecortex"]["params"]
    model_name = params.get("model", "gpt-5")
    ...
```

**Sessions:** `thread_id` is set from the session, so the same `sessionId` always reaches the same thread. Compile the graph with a checkpointer and it remembers the conversation for as long as the session's instance runs. Onecortex does not add a checkpointer for you: for memory that outlasts an instance, compile with one backed by your own database. See [Sessions](/build/sessions).

## Known limits

* Only the compiled graph is recognised. Export `builder.compile()`, not `builder`.
* Onecortex adds no checkpointer, and an in memory one lasts only as long as the session's instance.

## Troubleshooting

| You see | Do this |
| - | - |
| `Onecortex could not determine how to invoke the object at your entrypoint (type: StateGraph)` | You exported the builder. Export `builder.compile()`. |
| The agent forgets the previous message | Send the same `sessionId` on each call, and compile with a checkpointer. |

More on [Troubleshooting](/production/troubleshooting) and [Errors](/production/errors).
