The Contract an Agent Must Honor to Run Unattended

Moving an agent from a supervised session into an automated pipeline gets treated as a deployment step. It is a redesign. An agent that behaves well when a person is watching depends on that person in ways that stay invisible until they are gone: someone to answer a clarifying question, to notice when a run stalls, to catch a wrong answer before it flows downstream, to refuse a destructive action at the last second. A pipeline has none of that. The same agent, unchanged, does not degrade gracefully in an unattended context. It hangs a job that never had an input source, or it emits an apology where the next stage expected a record, or it does real damage that no one is present to interrupt.

The work of running an agent unattended is the work of re-homing every one of those human responsibilities into a mechanism. What comes out is a contract the interactive version never had to honor: input that is complete on arrival, a run that is bounded in time, output a machine can trust, an exit status that tells the truth, effects that survive being repeated, and an authority scoped tightly enough that a mistake no one catches stays small. Satisfy that contract and the agent becomes a composable step like any other in the system. Miss any clause and the failure is quiet, which in an unattended context is the dangerous kind.

Interactivity is a dependency on a person

Interactive operation is not merely a convenient interface. It is a set of assumptions baked into how the agent behaves, and every assumption is a dependency on a human being present. The most literal one surfaces first: an agent built to ask for input, running where no input source exists, waits forever. There is no human to type the answer, so the process does not fail and does not proceed. It consumes resources until some outer timeout kills it, and the pipeline behind it stalls the entire time.

The literal hang is only the clearest instance of a broader pattern. A supervised session lets the agent be underspecified because a person fills the gaps in real time. It lets output be loose because a person reads and interprets it. It lets the run be open-ended because a person is watching and will stop it. It lets authority be broad because a person can intervene the instant a run goes wrong. Each of those affordances is a quiet reliance on a human, and each becomes a distinct failure mode the moment the human is removed. Designing for unattended operation starts with taking inventory of what the person was actually doing, because that list is the specification for everything the automated version has to provide on its own.

One task, fully specified on arrival

An unattended agent should do one well-defined thing per invocation. This is not tidiness for its own sake. When a single invocation bundles several objectives, failure becomes ambiguous: the step failed, but which part, and what state did it leave behind? Ambiguous failure is expensive to diagnose when no one watched it happen, and it makes safe recovery nearly impossible because you cannot tell what to redo. A step that does one thing either accomplishes that thing or does not, and the rest of the system can reason about it cleanly.

The invocation also has to carry everything the agent needs, because a pipeline step retains nothing between runs. Anything it appears to know was put there by the caller, on this invocation, deliberately. This inverts the interactive habit entirely. In a session, context accumulates turn by turn, and the agent leans on what came before. A pipeline step begins from nothing. Any prior result, any configuration, any piece of state the task depends on has to be passed in explicitly at invocation time. Treating each run as if it starts from a blank slate is not a limitation to work around. It is the property that makes the step reproducible, and reproducibility is what lets an automated system trust the result.

The output is a contract with the next step

Downstream stages parse output, they do not read it. That single fact governs how an automated agent must communicate. A free-text answer that a human would understand at a glance is not a contract a program can hold, so the agent has to emit a structured, parseable result whose shape the next stage agrees on in advance. The interface between two automated steps is a data contract, and prose is not one.

The harder discipline is on the receiving side: never assume the contract was honored. An agent that succeeds may return a clean structured result, but an agent that fails often returns something else entirely, a plain-language explanation of what went wrong, exactly where the next stage expected data. So the consuming step validates the shape of what it received before trusting it, and treats anything unparseable as a failure of that step rather than passing malformed input forward. Letting it through is the more dangerous outcome, because a crash at least stops the line and announces itself, while a malformed value that slips past travels downstream and poisons everything computed from it, with no visible point of failure to trace back to.

Paired with the parseable result is the exit status, and in an automated context the exit status is the real return value. It is how the rest of the system learns whether to proceed, retry, or halt, without reading a word of the output. The contract is strict: the run reports success only when the work actually succeeded. An agent that hits an error, prints an explanation, and exits as though nothing went wrong is a specific and common hazard, because the pipeline reads the success signal, ignores the prose no program was going to parse, and advances on a result that does not exist. Encoding the true outcome in the status is not a formality. It is the difference between a failure that stops cleanly and one that propagates.

Retries make idempotency mandatory

Automated systems retry. A transient network error, a preempted worker, a timeout on some unrelated dependency, and the orchestrator runs the step again, often without any signal to the agent that this is a second attempt. That behavior is a feature of reliable pipelines, and it turns any effect the agent produces into something that may happen more than once.

If a second run means a second committed change, a duplicate record written, a redundant notification fired off to people who already got the first one, then the retry machinery that exists to make the system reliable becomes a source of corruption instead. The defense is to design the task so that running it twice leaves the same end state as running it once. Where the effect is naturally repeatable, this is free. Where it is not, the change needs a stable name for the intent behind it, attached by the agent or the tool it calls, so a repeat resolves to the recorded outcome instead of a fresh execution. Idempotency is not an optimization here. In a context that will retry on its own schedule, it is the property that keeps retries safe.

Every run needs a hard time bound

The failure between finishing quickly and never finishing is where unattended agents actually die. An agent waiting on an input that will never come, or blocked on an external service that has gone slow or silent, does not announce the problem. It simply does not return. Absent a bound of its own, the step keeps running until the runner’s top-level ceiling trips, and that ceiling is sized to catch pathological jobs, not to pace a healthy one, so it sits far above what any real step needs. In the meantime the resource is pinned, everything queued behind the step waits, and nothing surfaces the cause.

So each invocation carries its own tight time bound, chosen from what the task should actually take rather than what the runner will eventually tolerate. A step that exceeds it is terminated and reported as failed, which is a far better outcome than an indefinite wait, because a clean failure is something the system can retry or escalate while a hang is something it can only sit inside. Every external dependency the agent touches is a place it can block, and the time bound is the one control that turns an open-ended stall into a definite, actionable result.

Without a human, granted authority is the whole exposure

In a supervised run, broad permissions are tempered by the person watching. If the agent starts down a path it should not, someone can intervene before the damage lands. That live intervention is doing quiet safety work, and unattended operation removes it completely. There is no one to catch the bad decision, so whatever authority the agent was granted is now the full extent of what any mistake, bad input, or misfired plan can reach. The scope of the grant is the blast radius, with nothing standing between the two.

That makes tight scoping a requirement rather than a precaution. Every capability the task does not actively use is now pure exposure, held open with no countervailing benefit, so the grant should be pared to exactly what the one operation touches and nothing adjacent to it. The reasoning is specific to the unattended setting: the permission you leave on out of convenience is only harmless as long as someone is present to stop it from being used wrongly, and in a pipeline no one is.

The same missing human explains why credentials demand care here. A person operating interactively supplies authority implicitly by being who they are and being logged in. An automated run has to be handed that authority explicitly, and where those credentials live matters, because a pipeline definition is typically a versioned, widely readable artifact. Secrets belong in a runtime store and get injected into the run at execution time, never written into the definition itself, which would otherwise scatter the keys to the whole system across version history for anyone with read access to find.

An automated agent is infrastructure with a nondeterministic core

The through-line across every clause of the contract is the same: interactivity concealed a set of human responsibilities, and automation forces each one into an explicit mechanism. Completeness of input replaces the person who filled gaps. A validated output contract and an honest exit status replace the person who read and judged the result. A hard time bound replaces the person who noticed the stall. Idempotent effects replace the person who would have caught the double. Scoped authority and runtime secrets replace the person who was the last line of defense. None of these is exotic. They are exactly the properties any well-behaved process in a pipeline already provides.

That is the shift in stance the whole thing asks for. Stop treating the automated agent as a diminished version of the interactive one, missing its conversation and its supervisor. Treat it as infrastructure that happens to be nondeterministic on the inside. A component in an automated system is trusted because of the contract around it, not because of what it does internally, and the agent earns that same trust the same way. The nondeterminism at its core is precisely the reason the contract around it has to be rigid, because when the inside cannot be fully predicted, the boundary is the only thing you can hold firm.