Skip to main content
A Goose agent is defined by a recipe.yaml file in the Goose recipe format. Instead of writing TypeScript, you describe the agent’s instructions, parameters, and response schema in YAML. Guild validates the recipe at build time and runs it as a headless agent. Use this agent type when you already have a Goose recipe or want to define agent behavior in a portable, declarative YAML format without writing code.

Create a Goose agent

Replace the template recipe.yaml file with your Goose recipe, then save and run the agent like you would any other Guild agent.

Recipe file

Place recipe.yaml at the root of the agent’s version files. It must be valid YAML with a mapping at the document root. JSON recipes (recipe.json) aren’t supported. Guild doesn’t read other files next to recipe.yaml, except guild.yaml (see Integrations and sub-agents).

Recipe fields

Guild honors a subset of Goose recipe fields. Fields that Guild cannot honor are rejected at build time with an explicit error rather than silently ignored — a recipe author who declares an extension expects the agent to have it, and running without it would produce confusing behavior. At least one of instructions or prompt must be present. description must be a non-empty string, and instructions, prompt, and title must be strings when present.
A rejected field fails the build with an error that names it, such as Field 'extensions' is not supported on Guild.

Parameters

parameters is a list of mappings. Each entry defines one input variable available in the template.

user_prompt parameters

Parameters with requirement: user_prompt are treated as required on Guild. In Goose, these prompt the user interactively when missing. A headless run has no equivalent, and leaving them unset would leave literal {{ key }} text in the rendered prompt. On Guild, the input form serves the same role, so callers must supply them.

Default coercion

Recipe defaults may be written typed (default: 10) or as strings (default: "10"). Guild coerces the value to the declared type:
  • number — integer, float, or numeric string
  • boolean — YAML boolean or "true"/"false" (case-insensitive)
  • date — ISO YYYY-MM-DD string
  • select — must be one of options
  • string — any scalar
A non-coercible default is a build error.

Template variables

instructions and prompt are Jinja-style templates. Parameters are available as template variables. Validation rules:
  • Templates must be syntactically valid.
  • Every variable referenced in a template must be a declared parameter.
  • Every declared parameter must appear in instructions or prompt. activities don’t count, because Guild ignores them.
  • {{ recipe_dir }} is not available — Guild’s execution model has no recipe directory.
Templates render in a sandbox. Template expressions cannot access the host environment.

Skills

skills lists the Guild skills the agent can load. Write each one as a bare name, or as owner~name where owner is the agent’s own account.
At build time, Guild checks each reference:
  • skills must be a list of unique, non-empty strings. Entries are trimmed.
  • Every reference resolves against the agent’s own account, so an owner~name naming another account fails the build.
  • A reference resolves to the skill’s latest version. Version pins such as name@1.0.0 are rejected rather than ignored.
  • A reference that doesn’t resolve fails the build.
  • A public agent can’t depend on a private skill, because someone running the agent from another account couldn’t read it.
The build runs these checks in a Validate Guild skills step, then records each resolved skill on the version in a Store Goose skills step, so you can query a Goose agent’s skills like its tools. References that resolve to the same skill are recorded once. At run time, Guild writes each skill to <workspace>/.agents/skills/<name>/SKILL.md before the agent starts. Each file has name and description frontmatter followed by the skill body. Goose’s built-in skills extension is turned on only when the recipe declares skills. It finds the files, and the agent loads a skill’s body when it needs it. A recipe with no skills runs without the extension.

Input schema

Guild derives the agent’s input schema from the recipe’s parameters. The schema is JSON Schema Draft 2020-12. The top-level shape is:

text

text is always a string property in the schema.
  • Required when the recipe has no prompt — callers must provide a message. Description: "The message for the agent."
  • Optional when the recipe has a prompt. Description: "Optional message appended after the recipe's default prompt."

parameters object

parameters is included when the recipe declares at least one parameter. Parameters with requirement: required or requirement: user_prompt appear in the required array. The parameters object itself is required at the top level when its required array is non-empty.

Type mapping

Each property carries the parameter’s description. Optional parameters carry their coerced default.

Example

The recipe above produces:
If the recipe had no prompt field, text would also appear in the top-level required array.

Test an agent with parameters

The Test view in the online editor runs your agent against input you supply. When an agent defines parameters, the Test box expects a { text, parameters } JSON payload instead of a plain message — a shape that is easy to miss. To make it discoverable, the editor shows a This agent takes parameters callout in the Test view whenever the agent’s input schema declares parameters. The callout holds a ready-to-copy JSON starting point built from the agent’s real parameter keys. Each key is prefilled with its default value when it has one, the first option for a select parameter, or a typed placeholder otherwise ("" for strings, 0 for numbers, false for booleans). Copy the template, fill in your values, and send it to start the test session. For the recipe above, the callout shows:

Output schema

When response.json_schema is present, it is persisted verbatim as the agent’s output schema. The response field must follow these rules:
  • response must be a mapping that contains json_schema. A response without json_schema is a build error.
  • response.json_schema must be a mapping and a valid JSON Schema (Draft 2020-12).
When absent, the output schema defaults to the canonical text shape, so the agent’s final answer behaves like a prompt-driven agent’s text output:

Runtime behavior

At task start, the recipe is re-read from the version’s files and the input is applied as follows:
  1. Parameter values — declared defaults, overridden by values in input.parameters.
  2. Template rendering — instructions and prompt are rendered with the resolved parameter values.
  3. System prompt — the rendered instructions, when present.
  4. Initial message:
    • Recipe has no prompt → text is the initial message (the schema makes it required).
    • Recipe has a prompt, no text given → the rendered prompt.
    • Both present → the rendered prompt, then text, joined by a blank line.
  5. Workspace context — when present, prepended to the recipe’s prompt at task start, wrapped in a {% raw %} block so it is not treated as a template. The resulting prompt orders workspace context first, then the rendered recipe prompt, then text. It’s never added to the rendered instructions. Prepending the context inside the prompt carries it on every --resume turn, matching the native Goose runtime behavior.
Appending text after the recipe’s prompt mirrors Goose itself: in interactive mode, the recipe’s prompt is the first turn, and the user’s messages follow it.

Execution environment

A Goose agent runs in a container. By default, it uses the guildai~goosebox image. To run it in a different image, set environment in guild.yaml.

Chat input

Chat-originated input arrives as {"type": "text", "text": "..."}. When the agent’s schema includes a top-level text string property, that input maps to {"text": "<text>"}. A bare chat message can only start a Goose agent whose schema does not require parameters. Structured input from a parent agent is validated against the Goose agent’s input schema before any wrapping. When the input already conforms to the schema, it passes through unchanged, so a parent agent can send structured parameters directly. Only input that does not conform to the schema is wrapped as canonical text {"type": "text", "text": "<serialized input>"}.

Integrations and sub-agents (guild.yaml)

A Goose agent often needs to act on external systems, delegate work to other agents, or call built-in platform tools. Declare these in an optional guild.yaml file at the root of the agent’s version files, alongside recipe.yaml. Each integration operation, sub-agent, and built-in tool you declare becomes a tool the agent can call.
See the guild.yaml reference for every section, the built-in tools Goose agents can use, and the validation rules.

Environment field

Goose is the only agent type that accepts environment. It pins the agent to a runtime environment, written as "<owner>~<name>", such as acme~python-3.12. When omitted, the agent runs in the default guildai~goosebox image.

Build-time validation

Guild reads recipe.yaml twice:
  1. At build time, Guild validates the whole recipe and reports every error together rather than stopping at the first. On success, it stores description, input_schema, and output_schema on the agent version.
  2. At task start, Guild parses the recipe again from the version’s files, as described in Runtime behavior.
instructions, prompt, and parameters are not persisted on the version — the recipe file is their single source of truth. Because versions are immutable, a recipe that validated at build time parses identically at task start.
Last modified on October 15, 2026