How to handle state updates in multi-agent system?

Hey everyone,

I’m using a LangGraph prebuilt supervisor agent with AWS Bedrock and Bedrock Guardrails.
While testing my agent, I noticed an issue — once I trigger a Bedrock guardrail, my supervisor agent rejects everything I say afterward, even if the following messages are appropriate.

After debugging, I found that both the inappropriate human message and the guardrail AI message remain stored in the supervisor agent’s state.

To work around this, I implemented the following function as a pre_model_hook for my supervisor agent to remove those messages and “reset” the graph state without creating a new thread:

def remove_guardrails_messages(state):
    messages = state.get("messages", [])
    if not messages:
        return {}
    removed_ids = []
    for i in reversed(range(len(messages))):
        msg = messages[i]
        if not removed_ids and isinstance(msg, AIMessage):
            stop_reason = getattr(msg, "response_metadata", {}).get("stopReason")
            if stop_reason == "guardrail_intervened":
                removed_ids = [msg.id]
        elif removed_ids and isinstance(msg, HumanMessage):
            removed_ids += [msg.id]
            break

    if removed_ids:
        logger.debug(f"Removing guardrail AI/Human messages: {removed_ids}")
        return {"messages": [RemoveMessage(id=i) for i in removed_ids]}
    else:
        return {}

However, I found that the removed messages still get passed to the sub-agent, which then triggers its own guardrail, preventing it from responding correctly.

:red_question_mark: My Questions

  1. I use RemoveMessage(id) in the pre_model_hook to remove the previous conversation that triggered the guardrails, but I notice those messages are still being passed into the sub-agent’s state. Why is that happening? Do the supervisor agent and its sub-agents not share the same state?

  2. How can I ensure that once I modify the supervisor’s state, those changes are properly reflected (or passed down) to the sub-agent?

  3. Is there a recommended way to clear or sanitize guardrail-triggering messages before sub-agents receive them?

Any insights or best practices for handling this in LangGraph would be greatly appreciated

hey @mushroom88888888 Remove message probably works fine. You could implemnet some logic where if a message is rejected, you start a new thread all together. If you subagent inherits the supervisor state then it should get passed down.

Alternatively, you could use supervisor pattern that invokes subagents as tools (see Multi-agent - Docs by LangChain ), we launched a new prebuilt called create_agent and a concept of middleware that could help instead of using pre_model_hook: Middleware - Docs by LangChain