12. Agent Communication
Agents in a LangGraph team communicate exclusively through shared state—not through function call arguments, not through shared globals, not through message queues. The shared state dict serves as an inbox, an outbox, and a persistent memory layer simultaneously. This design makes the graph introspectable: at any checkpoint, the full history of agent interactions is present in the state dict.
Tool results from workers are stored in the messages field (using Annotated[list, add]). This history can grow large on long runs. Strategies to manage it: truncate old messages periodically (via a custom reducer that keeps only the last N), or move agent outputs into named fields (worker_results, findings, generated_code) once a worker completes so the messages list stays focused on the current turn.
For cross-worker data passing—e.g., the researcher produces findings that the coder uses—store the findings in a structured field:
class TeamState(TypedDict):
task: str
findings: Annotated[list[str], add]
generated_code: str | None
messages: Annotated[list[BaseMessage], add]
The coder worker reads state["findings"] in its context and writes to state["generated_code"]. No additional IPC is needed.
Between-team communication (e.g., one team produces a report that another team uses as input) happens at the process level: one team graph writes its final state to disk or a database, and the next team reads from that source on its initial invoke.
Local verification checkpoint
Run the smallest example from this chapter in a local workspace and record the package version, runtime, data path, and observed output. If the result depends on model size, vector count, CPU/GPU backend, or available memory, note that constraint beside the exercise so the lesson remains reproducible.
Run two sequential worker calls where the first appends to findings and the second reads from it. Confirm the second worker can access the first worker's output without any side-channel communication.