Reference for your agent. The precise shape of things — signatures, fields,
rules — written so an agent can read it and act. You do not need to: ask your
agent for what you want in words, and if it needs this page, hand it the URL or
use Copy page. What to ask for, and how to check it, is in Ask;
how to see what changed is in Look inside.
agent() in a program’s main.py, and the name it is
given is the whole of its identity.
"Assistant", because a run stores an address and nothing else: the
program it belongs to, and the agent inside it.
Asked, not stored
The prompt, the model, the provider, the tools and the iteration cap are not configuration the platform keeps. They are a question it asksmain.py, and the
answer is whatever the file says at the moment it is asked. Nothing is parsed at
publish, frozen into the run, or migrated afterwards.
A chat message is a run, so a line edited between two messages is read by the
second one, with nothing published in between.
Inside one run the question is asked once, at its start. What a turn can take
back are the points of the loop — context.build rebuilds what the model is
given on every turn, model.choose names the model on every turn. Those are in
Hooks.
The prompt is a file the program reads
system_prompt= takes text, or something to call. A callable is called at the
moment the spec is asked for, which is what makes an edit to
prompts/assistant.md land on the next message rather than on the next time
somebody imports main.py. A plain string is read once, when the declaration
runs.
That distinction is system_prompt= alone. Every other field is the value the
declaration computed — so a prompt read into a variable at the top of the file is
a prompt that changes when main.py changes, not when the file it came from
does.
prompts/ is data. The platform never opens it, your program does, so its format
is your business: markdown here, but a JSON file or a directory per language
would serve as well.
The seven fields
Whose credential it runs on
An agent names exactly one ofprovider and text_llm_endpoint_id, and neither
is optional. Naming both is refused rather than resolved: an agent that names a
provider while executing on somebody else’s credential lies to the person reading
it, and there is no reading of it that bills the right account. Naming neither is
refused too, in a sentence saying which of the two to write. model is required
alongside.
Both are checked when the run starts, which is the first moment anybody can ask
the program what it says. Nothing on the server parses your main.py at publish
time, so an agent naming a model nobody has credentials for publishes happily and
fails on the run that needs it.
The rest of the config
Anything else is passed through under the name the platform spells it with.How it generates
These are the platform’s own names for the generation settings, one name per idea, written flat on the declaration. The provider adapter answering the turn is what says each of them in its own API’s words.
Both starter agents write
reasoning="max", max_output_tokens=48000,
cache_control="5m" and modalities=["text", "image"].
A misspelling is an error where you wrote it
Every one of these used to be a key of a free-form mapping, where the same idea had a different name per provider — reasoning effort alone answered toreasoning_effort, thinking_effort, thinking_tokens and thinking_level —
and a misspelling was silence rather than an error. Now the declaration raises:
What the platform is told
When the loop asks whoAssistant is, this is the answer it gets back from the
declaration above:
agents travels as names. The prompt travels as the text the callable just
returned. Nothing else about the agent exists anywhere.
What changes when you edit each field
system_prompt— if it is a callable reading a file, the next message. If it is a string inmain.py, also the next message, becausemain.pyis re-imported when its own file moves.model,provider, generation settings — the next run. A run in flight keeps the model it started on, unlesshooks/model.pysays otherwise on a given turn.tools— the next run. The tool catalog is assembled once when the run starts. Editing the body of one of your own tools is different: that lands on the very next call.skills— the next run. This changes what the agent is told it has; the library’s files are on the machine either way.agents— the next run, and it changes two things at once: which agents this one may spawn, and what it is told it may spawn.max_iterations— the next run. It reacheshooks/stop.pyast.max_iterationsand nothing else reads it.- The agent’s name — every run that named the old one now asks for an agent the program does not declare. Add a declaration under the old name before you delete it, or accept that the old runs are unreadable.
An agent as somebody else’s tool
agents=[executor] names the declarations, and what travels is their names. What
the calling model calls it is that name sanitized into an identifier: lowercased,
spaces, hyphens and dots turned into underscores, everything outside [a-z0-9_]
dropped, runs of underscores collapsed, leading and trailing ones trimmed,
tool_ prefixed if the result would start with a digit, truncated to 64
characters. The Executor next door is executor.
description is the only thing the calling model knows before it decides. Unset,
the caller is told Call the <name> agent, which says nothing about what the
agent is for. Write it as an instruction to the caller rather than a summary of
the callee — the Executor’s description above spends its whole length on the two
things a caller gets wrong: that the sub-agent does not see the conversation, and
that what comes back should be the result rather than a description of it.
Sub-agents is the rest of that story.
