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.

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.
description: Review code with a configurable focus
instructions: You are a {{ language }} reviewer focused on {{ focus }}.
prompt: Review the code provided below.
parameters:
  - key: language
    input_type: select
    requirement: required
    description: Language under review
    options: [python, typescript]
  - key: focus
    input_type: string
    requirement: optional
    default: best practices
    description: Review focus area

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.
FieldTreatment
descriptionHonored — required. Persisted as the version and agent description.
instructionsHonored — rendered and sent to the agent as its system prompt.
promptHonored — rendered, used as the default initial message.
parametersHonored — drives the input schema and template rendering.
responseHonoredjson_schema becomes the output schema.
titleIgnored — validated as a string if present; Guild uses the agent name.
versionIgnored
authorIgnored
activitiesIgnored — desktop-only in Goose.
extensionsRejected — Guild does not honor recipe extensions.
settingsRejected — provider and model are platform-controlled.
sub_recipesRejected — not supported.
retryRejected — not supported.
Any unknown fieldRejected — catches typos and unreviewed future fields.
At least one of instructions or prompt must be present.

Parameters

parameters is a list of mappings. Each entry defines one input variable available in the template.
FieldRule
keyRequired. Must match ^[a-zA-Z_][a-zA-Z0-9_]*$. Must be unique across the list.
input_typeRequired. One of string, number, boolean, date, select. file is not supported.
requirementRequired. One of required, optional, user_prompt.
descriptionRequired, non-empty string. Shown in the generated input form.
defaultRequired for optional parameters; forbidden for required and user_prompt parameters.
optionsRequired non-empty list of unique strings for select; forbidden for other types.

user_prompt parameters

Parameters with requirement: user_prompt are treated as required on Guild. In Goose, these prompt the user interactively when missing. On Guild, the input form serves the same role — 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 at least one template.
  • {{ 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.

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": "...", "parameters": { "<key>": "<value>", ... } }

text

text is always a string property in the schema.
  • Required when the recipe has no prompt — callers must provide a message.
  • 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

input_typeJSON Schema property
string{"type": "string"}
number{"type": "number"}
boolean{"type": "boolean"}
date{"type": "string", "format": "date"}
select{"type": "string", "enum": [<options>]}
Each property carries the parameter’s description. Optional parameters carry their coerced default.

Example

The recipe above produces:
{
  "type": "object",
  "properties": {
    "text": {
      "type": "string",
      "description": "Optional message appended after the recipe's default prompt."
    },
    "parameters": {
      "type": "object",
      "properties": {
        "language": {
          "type": "string",
          "enum": ["python", "typescript"],
          "description": "Language under review"
        },
        "focus": {
          "type": "string",
          "default": "best practices",
          "description": "Review focus area"
        }
      },
      "required": ["language"],
      "additionalProperties": false
    }
  },
  "required": ["parameters"],
  "additionalProperties": false
}
If the recipe had no prompt field, text would also appear in the top-level required array.

Output schema

When response.json_schema is present, it is persisted verbatim as the agent’s output schema. When absent, the output schema defaults to the canonical text shape, so the agent’s final answer posts to chat like an LLM agent:
{
  "type": "object",
  "properties": {
    "type": {"type": "string", "const": "text"},
    "text": {"type": "string"}
  },
  "required": ["type", "text"],
  "additionalProperties": false
}

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 renderinginstructions and prompt are rendered with the resolved parameter values.
  3. System prompt — the rendered instructions, when present.
  4. Initial message:
    • Recipe has no prompttext 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. Prepending the context inside the prompt carries it on every --resume turn, matching the native Goose runtime behavior.

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.

Integrations and sub-agents (guild.yaml)

A Goose agent often needs to act on external systems or delegate work to other agents. Declare these dependencies in an optional guild.yaml file placed at the root of the agent’s version files, alongside recipe.yaml. Each integration operation and each sub-agent you declare becomes a tool the agent can call. Omit guild.yaml when the agent needs no external integrations or sub-agents.
integrations:
  - name: acme~github
    version: ^1.4.0
    tools: [github_repos_get, github_issues_list]

sub_agents:
  - name: acme~research
    version: ^1.0.0

Integration fields

Each entry under integrations declares one integration dependency.
FieldRule
nameRequired. The integration identifier, such as acme~github.
versionRequired. A semver range, such as ^1.4.0, that must resolve to a published version.
toolsOptional. A list of operations to expose as tools. When omitted, all operations of the resolved integration version are made available.

Sub-agent fields

Each entry under sub_agents declares one sub-agent dependency.
FieldRule
nameRequired. The sub-agent identifier, such as acme~research.
versionRequired. A semver range, such as ^1.0.0, that must resolve to a published version.

Validation rules

Guild validates guild.yaml at build time, alongside recipe.yaml.
  • Version resolution — the version range for each integration and sub-agent must resolve to a published version. A range that resolves to no published version is a build error.
  • Tool verification — when tools is specified for an integration, each listed tool must carry the integration’s service prefix (for example, github_) and map to a real operation on the resolved integration version. A tool that does not match an available operation is a build error. When tools is omitted, all operations of the resolved integration version are available.
  • Access and permissions — a public agent cannot depend on a private integration or a private sub-agent, and a sub-agent cannot be archived. See Versions for the full dependency visibility rules.

Build-time validation

Guild validates the full recipe when you publish a version. All validation errors are reported together — not fail-fast. On success, three values are persisted on the agent version: description, input_schema, and output_schema.
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.