What a workflow's code may do
Every codified step declares what it can reach before it runs, and the console shows you that declaration step by step.
A codified workflow is a list of steps, and the repeatable ones are small Python functions the assistant wrote. This page covers where that code runs, what it is allowed to touch, and how you can see the answer without reading any of it.
Every code step carries a plain-language explanation of what it does. That field is required and cannot be left empty, so a codified workflow stays readable to the person who owns it.
A fresh sandbox, every single time
One invocation gets one sandbox. It is created for that call, and it is torn down afterwards whatever happened, success or failure.
The sandbox starts from an empty environment. Only what the step declared is put into it. None of the platform's own configuration goes in: not our model keys, not our database, not our host. There is no local or fast path that skips this and none can be added.
The Python version is pinned to the workflow itself, not to whatever the server happens to run, so a step that worked in June behaves the same way in December. Only the standard library is available. Nothing gets installed, so a step that reaches for a third-party package fails on its import and goes into repair.
Default deny
A step declares two things, and both default to nothing at all.
Network. none means no network and no DNS. public_egress means the open
internet. There is deliberately no per-domain allowlist: a hand-written list of
hostnames goes stale as a provider moves its endpoints, and it would fail in
production against a step that worked perfectly while you were building it.
Connections. A step names the connections it needs by an alias, and receives each one as an environment variable built from that alias. What the stored step holds is a reference to the connection, never the credential itself, so the workflow can be read, compared and exported without exposing anything.
A step that declares neither gets no network, no DNS and no credentials. That is the starting point, not a setting anyone has to remember to apply.
The declaration is checked when the workflow is parsed, which happens on every change during the interview, when you confirm, and again before the engine runs anything. Nothing is ever executed unparsed.
What the console shows you
The workflow screen has a panel called "What each step can reach". It lists every step that runs code, including the ones that reach nothing, so an absent row can never quietly mean "nothing to see here". Each row gives the step, whether it has internet access, and which connections it is granted by name.
The panel says what it is, in its own words: "This is what each step is permitted to reach, not a review of what its code does." That distinction is the honest one. Permission is a fact the engine enforces. What the code does with that permission is a different question, and this panel does not answer it.
Nothing re-runs a step behind your back
A step that failed while it had internet access is never retried automatically. A request can complete at the other end after the client has given up waiting, so a blind second attempt is a second invoice, a second message, a second refund.
Instead the failure goes to the agent watching the run, which can retry the step with different inputs or stop the workflow and bring it to you. It is told plainly that a timeout, or any error that leaves the outcome unknown, means stop.
The authoring guidance pushes in the same direction: the safely repeatable part of a task, building the request, belongs in its own step with no network, and the send stays alone in the step that has it.
Credentials do not leak into the record
Every value a run can observe, the credentials in its sandbox, the connections granted to its steps, the key paying for its model calls, is collected once per run and handed to every piece of code that writes something down. A writer that forgets to take it fails the type check, so the guard cannot be skipped by somebody who did not know about it.
Three consequences you can rely on:
- A step's inputs are stored verbatim, so they are not allowed to carry fields
named
secret,credentials,api_keyortoken. Credentials travel separately, in the environment. - If code hands its credential straight back as output, or an error message quotes it, the value is removed before anything downstream sees it.
- A run suspended on an approval stores its state with the values stripped out and the names kept. On resume, the credentials are looked up again from your account, which is also why a key rotated during the wait takes effect.
The boundary this does not cross
A step that was granted a credential can use that credential. That is the whole point of granting it, and no sandbox can prevent it. What the boundary buys you is blast radius: the grant is one connection, named on the step, under your account, visible in the console, and revocable at any time.