> For the complete documentation index, see [llms.txt](https://weavescope.gitbook.io/beam_weaver/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://weavescope.gitbook.io/beam_weaver/core-components/graph.md).

# Graph

BeamWeaver translates LangGraph behavior into Elixir modules, behaviours, and supervised execution. It does not copy Python factories or base classes.

## Graphs

Build an immutable graph, compile it, then invoke it:

```elixir
graph =
  BeamWeaver.Graph.new()
  |> BeamWeaver.Graph.add_reducer(:messages, fn existing, update ->
    existing ++ List.wrap(update)
  end)
  |> BeamWeaver.Graph.add_node(:answer, fn state ->
    %{messages: ["hello #{state.name}"]}
  end)
  |> BeamWeaver.Graph.add_edge(BeamWeaver.Graph.start(), :answer)
  |> BeamWeaver.Graph.add_edge(:answer, BeamWeaver.Graph.end_node())
  |> BeamWeaver.Graph.compile!()

{:ok, state} = BeamWeaver.Graph.Compiled.invoke(graph, %{name: "Ada", messages: []})
```

Compiled graphs support:

* `invoke/3`, `stream_events/3`, `batch/3`, `async_invoke/3`, and `async_batch/3`
* reducer-based state merges
* guarded routes with `when:` and dynamic fan-out with `BeamWeaver.Graph.Send`
* explicit routing with `BeamWeaver.Graph.Command`
* interrupts before or after configured nodes
* checkpoint-backed `get_state/2`, `get_state_history/3`, and `update_state/4`

Event streaming returns an `Enumerable` of typed `%BeamWeaver.Stream.Envelope{}` values. Use `BeamWeaver.Graph.Compiled.stream_events/3` for graph progress, custom updates, task metadata, and final lifecycle events.

## Checkpoints and Memory

Checkpointing and memory are contracts:

* `BeamWeaver.Checkpoint.Saver`
* `BeamWeaver.Memory.Store`

ETS implementations are available for local execution and tests:

```elixir
checkpointer = BeamWeaver.Checkpoint.ETS.new()
store = BeamWeaver.Memory.ETS.new()
```

Postgres support uses Ecto through adapters that implement the same behaviours:

```elixir
checkpointer = BeamWeaver.Checkpoint.Ecto.new(repo: MyApp.Repo)
store = BeamWeaver.Memory.Ecto.new(repo: MyApp.Repo)
```

Use the SQL helper on each Ecto adapter to create the required Postgres tables in your application schema setup.

See [Persistence](/beam_weaver/capabilities/persistence.md) for checkpoint state history, updates, pending writes, storage optimization, and adapter scope. See [Durable Execution](/beam_weaver/capabilities/durable_execution.md) for checkpoint-backed recovery and resume design. See [Fault Tolerance](/beam_weaver/capabilities/fault_tolerance.md) for node retries, timeouts, error handlers, and failure policies.

## Agents

Agents are user modules:

```elixir
defmodule MyApp.SupportAgent do
  use BeamWeaver.Agent

  reducer :messages, fn existing, update -> existing ++ List.wrap(update) end
  node :prepare, &__MODULE__.prepare/2
  node :reply, &__MODULE__.reply/2
  edge BeamWeaver.Graph.start(), :prepare
  edge :prepare, :reply
  edge :reply, BeamWeaver.Graph.end_node()

  def prepare(state, _runtime), do: Map.put_new(state, :messages, [])

  def reply(state, runtime) do
    greeting = Map.get(runtime.context || %{}, :greeting, "hello")
    %{messages: ["#{greeting}, #{state.name}"]}
  end
end
```

Call it directly:

```elixir
{:ok, state} = MyApp.SupportAgent.invoke(%{name: "Ada"}, context: %{greeting: "hi"})
```

Or supervise it and call the server:

```elixir
{:ok, pid} = MyApp.SupportAgent.start_link([])
BeamWeaver.Agent.Server.invoke(pid, %{name: "Ada"})
```

## DAG Composition

Use explicit start/end edges for graph boundaries, `deps:` for fan-in, and `when:` for simple constraints:

```elixir
graph =
  BeamWeaver.Graph.new(name: "ResearchPipeline")
  |> BeamWeaver.Graph.add_reducer(:reviews, fn left, right -> Map.merge(left, right) end)
  |> BeamWeaver.Graph.add_node(:plan, fn state -> %{plan: state.topic} end)
  |> BeamWeaver.Graph.add_node(:facts, FactsAgent, deps: :plan)
  |> BeamWeaver.Graph.add_node(:market, MarketAgent, deps: :plan)
  |> BeamWeaver.Graph.add_node(:facts_check, FactsVerifier,
    deps: :facts,
    output: [:reviews, :facts]
  )
  |> BeamWeaver.Graph.add_node(:market_check, MarketVerifier,
    deps: :market,
    output: [:reviews, :market]
  )
  |> BeamWeaver.Graph.add_node(:final, SummaryAgent,
    deps: [:facts_check, :market_check],
    when: %{status: :accepted}
  )
  |> BeamWeaver.Graph.add_edge(BeamWeaver.Graph.start(), :plan)
  |> BeamWeaver.Graph.add_edge(:facts_check, :facts,
    when: %{status: :needs_revision},
    max_runs: 2
  )
  |> BeamWeaver.Graph.add_edge(:market_check, :market,
    when: %{status: :needs_revision},
    max_runs: 2
  )
  |> BeamWeaver.Graph.add_edge(:final, BeamWeaver.Graph.end_node())
  |> BeamWeaver.Graph.compile!()
```

## Testing Standard

Graph and agent tests should check behavior: state transitions, persisted history, stream payloads, interrupts, retries, tool/model errors, and adapter contract coverage. Do not add tests that only assert copied constants, assigned values, or supervisor children whose absence would crash the app.

## Related Guides

* [Thinking In BeamWeaver](/beam_weaver/thinking_in_beamweaver.md)
* [Workflows And Agents](/beam_weaver/workflows_and_agents.md)
* [Agents](/beam_weaver/core-components/agents.md)
* [Persistence](/beam_weaver/capabilities/persistence.md)
* [Event Streaming](/beam_weaver/capabilities/event_streaming.md)


---

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

```
GET https://weavescope.gitbook.io/beam_weaver/core-components/graph.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.
