An agent is just JSON, with Python expressions.
Here is a complete agent. It sends the user’s question to a language model and streams the answer back.
{
"functions": {
"main": {
1Every agent starts in the function named main. An agent can have other functions as well, and the next example adds one. "commands": {
"llm": {
2The llm command sends a prompt to a model and streams the answer back to the user as it is generated. "profile": "gpt5_mini",
3The profile named here holds the model name, the API key and the host, so the agent file contains none of them. "prompt": "answer",
4The prompt named here is set in the UI, not in this file. Its user text is { sys.query }. The braces mark a Python expression, and sys.query holds the question the user asked. "streamOutput": true
}
}
}
}
}- 1Every agent starts in the function named
main. An agent can have other functions as well, and the next example adds one. - 2The
llmcommand sends a prompt to a model and streams the answer back to the user as it is generated. - 3The profile named here holds the model name, the API key and the host, so the agent file contains none of them.
- 4The prompt named here is set in the UI, not in this file. Its user text is
{ sys.query }. The braces mark a Python expression, andsys.queryholds the question the user asked.
Every agent has the same shape.
An agent is a set of named functions, and a function is a list of commands that run in the order they are written. Each command is a key, and its value carries the command’s fields. A string value enclosed in braces is a Python expression; any other string is plain text. Where a command reaches outside the agent, to a model, an API or a database, it names a profile, and the profile holds the connection details. An llm command also names a prompt, which is set in the UI and holds the text sent to the model.
Now give it an API to call
This agent answers questions about orders. It has a function that looks up an order through an API, and the model decides when to call that function. Agent files are JSONC, which is JSON that allows comments, so this one has a few.
{
// Answers questions about orders.
// The model calls getOrder when it needs one.
"functions": {
"getOrder": {
"description": "Looks up one order by its number.",
"args": { "orderId": { "type": "str" } },
1A function that declares arguments becomes a tool the model can call. The model reads the description, decides when the function is needed, and supplies the arguments itself. "commands": {
"progress": "Looking up the order",
2Each of these two commands is a single line. The progress command shows the user a short message while the agent works. The log command writes a line to the agent server’s log, which stays in your environment. "log": "{ f'Order {orderId} requested by {sys.userEmail}' }",
"api": {
3The api command calls the API that the profile names. The host, the credentials and the headers come from the profile, and only the path comes from the agent. The parsed response is placed in result. "profile": "orders",
"path": "{ f'/orders/{orderId}' }"
},
"trace": "{ f'Status: {result['status']}' }",
4The trace command writes to the execution trace that you read while validating a draft. In production it does nothing. "progress.done": "Found the order",
5To use a command a second time in the same function, add a dot and a suffix to its name. The suffix can be any word or number; it only keeps the two keys distinct. "return": "{ result }" // the order goes back to the model
}
},
"main": {
"commands": {
"llm": {
"profile": "gpt5_mini",
"prompt": "orders",
"functions": ["getOrder"],
6Listing getOrder here gives the model that function as a tool. The model calls it whenever a question needs an order looked up. "streamOutput": true
}
}
}
}
}- 1A function that declares arguments becomes a tool the model can call. The model reads the description, decides when the function is needed, and supplies the arguments itself.
- 2Each of these two commands is a single line. The
progresscommand shows the user a short message while the agent works. Thelogcommand writes a line to the agent server’s log, which stays in your environment. - 3The
apicommand calls the API that the profile names. The host, the credentials and the headers come from the profile, and only the path comes from the agent. The parsed response is placed inresult. - 4The
tracecommand writes to the execution trace that you read while validating a draft. In production it does nothing. - 5To use a command a second time in the same function, add a dot and a suffix to its name. The suffix can be any word or number; it only keeps the two keys distinct.
- 6Listing
getOrderhere gives the model that function as a tool. The model calls it whenever a question needs an order looked up.
Twenty commands are all you need
Every agent is written with these commands and nothing else. You concentrate on what the agent should do, and the framework takes care of everything around it.
A command is written as a single line when a string is all it needs, and as an object when it takes more than one field. The syntax page describes the rules in full.
Describe an agent and read the definition it produces
Draft with AI writes the first draft of an agent from a sentence that describes what the agent should do. The same assistant is available inside the draft editor, where it can also change an agent that already exists. Try it here with a description of your own, or with one of the examples.
Draft, validate, publish
An agent goes through three stages on its way to the users who will run it.
Draft
A draft is private to the developer who created it. You can write it in the editor, which knows the agent language and points out mistakes as you type, or let Draft with AI write the first version from a sentence and then refine it by hand.
Validate
Validation checks the definition against the schema and the security rules, and confirms that everything the agent refers to exists in the account. The agent server then runs the draft on a sample question and shows the trace: every command that ran, what it was called with, and what it returned. An agent cannot be published until validation passes.
Everything the agent did not spell out is handled by the agent runtime: credentials, connections to outside systems, streaming, conversation memory, pausing for a person’s answer, and the time and cost limits that every run stays within.
Where to read more
The agent definition section of the documentation explains the structure of an agent, its variables and its Python expressions in detail. The command reference describes every command. The getting started guide walks through writing and running a first agent.

