Your agent is three minutes into a run and heading somewhere wrong. You do not want to kill it and lose the context it built. So what are your actual options?
There are three, and they answer three different questions. Inject when you need to redirect a live run without pausing it. Interrupt when a decision genuinely has to block until a human answers. Gate when the worry is not when the agent acts but which actions it is allowed to take. Everything below is a shipped, documented mechanism — not a pattern you have to hand-roll.
Killing the run is the expensive option. All three of these let you keep the context you already paid for.
Inject: nudge a live run mid-turn#
This is the newest arrival. Microsoft Agent Framework shipped message-injection middleware in Python 1.11.0 (released July 10, 2026). The mechanism is narrow and specific: tools or host code can enqueue messages into an active run, and those messages are drained into the next model call within the same AgentSession (PR #6998). A companion change wired it into create_harness_agent and the harness console sample so a running harness agent can be nudged mid-turn (PR #7027). We covered the wider 1.11.0 release — including the Skills API going stable — in what Microsoft Agent Framework shipped in July.
The important property is that the run does not stop. You are not pausing execution and waiting for a reply. You drop a message into the queue — "the user just changed their mind, prioritize the refund path" — and the agent picks it up on its next turn. It is fire-and-forget steering, not a blocking handshake.
That makes it the right fit for supervisory course-correction: a human (or a monitoring agent) watching a long autonomous run who occasionally wants to redirect without breaking flow. It is the wrong fit when the correction is mandatory and the agent must not proceed until it lands — injection has no guarantee about when the message is consumed, only that it will be, on the next model call.
Interrupt: pause the graph, wait for an answer#
LangGraph takes the opposite stance. Its interrupt() function stops the graph mid-node, saves state through the persistence layer, and waits — indefinitely — until you resume. The docs are explicit that this is a hard dependency: you must configure a checkpointer, because the whole model relies on freezing graph state to disk (or a database) and thawing it later.
Resuming is a first-class operation, not a re-run. You call the graph again with Command(resume=value), using the same thread_id, and the value you pass becomes the return value of the original interrupt() call — execution continues from exactly where it paused.
from langgraph.types import interrupt, Command
def review_node(state):
decision = interrupt({"proposed": state["draft"]}) # blocks here
return {"final": decision}
# ...later, after a human replies:
graph.invoke(Command(resume="approved"), config={"configurable": {"thread_id": "t-1"}})
This is checkpoint-and-resume, and it is the model to reach for when a step must not continue without input: an approval before sending money, a clarifying question the agent cannot answer itself, a review gate on generated output. The cost is that you own persistence and thread identity, and the run is genuinely halted — fine when a human is expected, awkward for high-throughput autonomous work where blocking is a liability.
Gate: approve actions, not moments#
The third model does not care about timing at all. It cares about capability. Microsoft Agent Framework's skill approval, stabilized in .NET 1.13.0 (released July 3, 2026), is the clean example. The skills provider exposes three tools an agent can call — load_skill, read_skill_resource, and run_skill_script — and all three require approval by default. Nothing loads or executes without oversight, and you relax the gate selectively for operations you trust. It is a pre-execution allowlist expressed as human-in-the-loop approvals on the riskiest verbs.
OpenAI's Agents SDK offers a related but differently-shaped gate: guardrails. Input and output guardrails run alongside the agent, and each returns a GuardrailFunctionOutput; if tripwire_triggered is True, the SDK raises an exception and halts execution. Input guardrails fire before the agent runs (saving tokens and blocking bad requests); output guardrails validate what the agent produced.
from agents import input_guardrail, GuardrailFunctionOutput
@input_guardrail
async def block_pii(ctx, agent, user_input):
flagged = contains_pii(user_input)
return GuardrailFunctionOutput(output_info={}, tripwire_triggered=flagged)
The distinction that matters: a gate is a boundary, not a pause. Skill approval asks "is this specific action allowed?" per call. A guardrail tripwire is a wall the run hits and dies against. Neither collects freeform human direction the way an interrupt does — they enforce policy, they do not gather input.
So which do you pick?#
Start from the question you are actually asking.
- "I want to redirect a run that is already going, without stopping it." Message injection. It is the only one of the three built to modify an in-flight run without blocking it.
- "This step must not proceed until a human decides." LangGraph
interrupt()with a checkpointer. It is the only one that cleanly persists, blocks, and resumes with the human's value threaded back in. - "I do not trust the agent to run certain actions unsupervised." A gate — skill approval for per-action allowlisting, guardrails for hard input/output boundaries.
They compose. A production agent can gate its dangerous tools, interrupt for high-stakes approvals, and accept injected nudges for everything in between. The mistake is reaching for the kill switch — restarting a run throws away context you already paid to build. Pick the mechanism that matches the question, and the run keeps its memory.



