Skip to main content
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.
An agent is a call to agent() in a program’s main.py, and the name it is given is the whole of its identity.
The variable is only how the rest of the file refers to it. What travels to the platform is "Assistant", because a run stores an address and nothing else: the program it belongs to, and the agent inside it.
Two agents of one program may not share a name — the loop asks for one by name, and the first declaration matching it answers. Renaming an agent leaves every run that named the old one asking for an agent the program no longer declares.

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 asks main.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 of provider 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 to reasoning_effort, thinking_effort, thinking_tokens and thinking_level — and a misspelling was silence rather than an error. Now the declaration raises:
A value outside the ladder is refused the same way:

What the platform is told

When the loop asks who Assistant 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 in main.py, also the next message, because main.py is re-imported when its own file moves.
  • model, provider, generation settings — the next run. A run in flight keeps the model it started on, unless hooks/model.py says 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 reaches hooks/stop.py as t.max_iterations and 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.