Citation continuity across subagents
Shared state is about more than pretty code. It is about keeping evidence attached to answers. When the RAG subagent pulls policy chunks and writes them into retrieved_docs, the citations list becomes part of the final response. When the billing subagent fills customer_record, the claims subagent on the next turn can reuse it without re-querying.
async def policy_agent_node(state: ClaimState) -> Dict[str, Any]:
query = state.get('user_input', '')
hits = search_policies(query, k=4)
if hits:
context = '\n\n'.join(
f"[source: {h['source']}]\n{h['content']}" for h in hits
)
else:
context = '(no policy documents indexed yet)'
provider = get_llm_provider()
answer = await provider.generate_text(
POLICY_PROMPT.format(user_input=query, context=context),
max_tokens=500,
temperature=0.2,
)
citations = sorted({h['source'] for h in hits})
return {
'retrieved_docs': hits,
'answer': answer,
'citations': citations,
}The policy subagent returns three fields. retrieved_docs goes into state so a later turn can reference the same chunks without re-searching. citations is exposed to the API response so the UI can show sources next to the answer. answer is what the user reads.
In the supervisor pattern we built, only one subagent runs per turn. The supervisor routes to exactly one leaf and then the graph terminates. So answer is written exactly once. If you later add fan-out where two subagents run in parallel, LangGraph has reducer annotations you attach to fields. For lists you can use operator.add to concatenate. For scalar fields like answer, you either pick one or change the schema so each subagent writes to its own key.
Ordering exercise: Order the state updates for a billing question about a past claim
Loading practice…
Quiz: Quiz
Loading practice…