Ejection logic
Ejection logic is the agent’s escape hatch: a way to stop the loop or hand over when something is going wrong, written as ordinary code the model cannot talk its way past. A stop button is the user’s version of it.
Triggers
A pre-check filter runs before the model on every turn and looks for three things.
- User frustration: the user asks for a person, or the conversation is going round in circles.
- User termination: the user says stop or cancel.
- Policy or safety violation: a guardrailLLM guardrailsChecks around the model, so a bad input or a bad output is caught by something that does not rely on the model behaving.Opens in a new tab flagged the request.
Any one of them ejects. The eject path ends the run, and for frustration or a violation it hands the conversation to a human along with what has happened so far.
In LangGraph
The pre-check is a conditional edge from START. It returns the name of the next node, so the model is never reached when it returns "eject".
from typing import Literal, TypedDict from langgraph.graph import END, START, StateGraph class State(TypedDict, total=False): message: str policy_flag: bool reply: str def eject_reason(state: State) -> str | None: text = state["message"].lower().strip() if text in {"stop", "cancel"}: return "user_termination" if "talk to a human" in text or "this is useless" in text: return "user_frustration" if state.get("policy_flag"): return "policy_violation" return None def pre_check(state: State) -> Literal["eject", "agent"]: return "eject" if eject_reason(state) else "agent" graph = ( StateGraph(State) .add_node("agent", lambda s: {"reply": "...the model answers..."}) .add_node("eject", lambda s: {"reply": f"Stopped ({eject_reason(s)}). A person takes over."}) .add_conditional_edges(START, pre_check) .add_edge("agent", END) .add_edge("eject", END) .compile())Stopping conditions
Ejection also covers runaway loops. Anthropic recommends stopping conditions such as a maximum number of iterations to keep an agent under control. LangChain has model and tool call limit middleware for this, with an exit behavior of 'end' for a graceful stop or 'error' to raise.
The catch
Keyword checks for frustration are crude. A classifier does it better but is probabilistic itself, so keep the stop and terminate triggers deterministic, and let the fuzzy one only add a handover.
Sources
- Building effective agents, Anthropic · accessed October 5, 2026
- Built-in middleware, LangChain Docs · accessed October 5, 2026