Agents - Dark-Alex-17/coyote GitHub Wiki

Agents in Coyote follow the same style as OpenAI's GPTs. They consist of 3 parts:

  • Role - Tell the LLM how to behave
  • RAG - Pre-built knowledge bases specifically for the agent
  • Function Calling (#2) - Extends the functionality of the LLM through custom functions it can call

Looking for declarative, multi-step workflows? See Graph Agents: a YAML-driven workflow engine where each step (LLM call, script, user prompt, child-agent spawn) is its own typed node. Useful when an agent's behavior follows a fixed shape rather than a single open-ended LLM loop.

Agent example

Agent configuration files are stored in the agents subdirectory of your Coyote configuration directory. The location of this directory varies between systems so you can use the following command to locate yours:

coyote --info | grep 'agents_dir' | awk '{print $2}'

If you're looking for more example agents, refer to the built-in agents.

Running an agent inside a Docker Sandbox? If the agent needs external binaries (pandoc, usql, etc.) or specific network domains, ship a per-agent sbx-mixin.yaml alongside its config.yaml. See Sandbox Support at the bottom of this page.


Directory Structure

Agent configurations often have the following directory structure:

<coyote-config-dir>/agents
    └── my-agent
        ├── config.yaml
        ├── tools.sh
            or
        ├── tools.py
            or
        ├── tools.ts

This means that agent configurations often are only two files: the agent configuration file (config.yaml), and the tool definitions (agents/my-agent/tools.sh, tools.py, or tools.ts).

To see a full example configuration file, refer to the example agent config file.

The best way to understand how an agent is built is to go step by step in the following manner:


1. Metadata

Agent configurations have the following settings available to customize each agent:

# Model Configuration
model: openai:gpt-4o                 # Specify the LLM to use
temperature: null                    # Set default temperature parameter, range (0, 1)
top_p: null                          # Set default top-p parameter, with a range of (0, 1) or (0, 2), depending on the model
reasoning_effort: null               # Set the reasoning effort level for models that support it (e.g. low, medium, high)
# Agent Metadata Configuration
agent_session: null                  # Set a session to use when starting the agent. (e.g. temp, default); defaults to globally set agent_session
compression_model: null              # Model to use when compressing this agent's session (overrides the global compression_model); falls back to the current model with a printed warning if it fails
# Agent Configuration
name: <agent-name>                   # Name of the agent, used in the UI and logs
description: <description>           # Description of the agent, used in the UI
version: 1                           # Version of the agent
# Function Calling Configuration
mcp_servers:                         # Optional list of MCP servers that the agent utilizes
  - github                           # Corresponds to the name of an MCP server in the `<coyote-config-dir>/mcp.json` file
mcp_tools:                           # Optional per-server tool whitelists for the agent's MCP servers; a map of
  github:                            # server name -> tool-name patterns (`*`/`?` globs, YAML list values only).
    - get_*                          # See the MCP Servers wiki page, "Restricting MCP Tools (Tool Whitelists)"
    - list_*
global_tools:                        # Optional list of additional global tools to enable for the agent; i.e. not tools specific to the agent
  - web_search
  - fs
  - python
# Todo System & Auto-Continuation (see "Todo System & Auto-Continuation" section below)
auto_continue: false                 # Enable automatic continuation when incomplete todos remain
max_auto_continues: 10               # Maximum continuation attempts before stopping
inject_todo_instructions: true       # Inject todo tool instructions into system prompt
continuation_prompt: null            # Custom prompt for continuations (optional)
# Sub-Agent Spawning (see "Sub-Agent Spawning System" section below)
can_spawn_agents: false              # Enable spawning child agents
max_concurrent_agents: 4             # Max simultaneous child agents
max_agent_depth: 3                   # Max nesting depth (prevents runaway)
inject_spawn_instructions: true      # Inject spawning instructions into system prompt
summarization_model: null            # Model for summarizing sub-agent output (e.g. 'openai:gpt-4o-mini')
summarization_threshold: 4000        # Char count above which sub-agent output is summarized
escalation_timeout: 0                # 0 = wait indefinitely for escalated user input (default); N = give up after N seconds

As mentioned previously: Agents utilize function calling to extend a model's capabilities. However, agents operate in isolated environment, so in order for an agent to use a tool or MCP server that you have defined globally, you must explicitly state which tools and/or MCP servers the agent uses. Otherwise, it is assumed that the agent doesn't use any tools outside its own custom defined tools.

And if you don't define a agents/my-agent/tools.sh, agents/my-agent/tools.py, or agents/my-agent/tools.ts, then the agent is really just a role.

You'll notice there are no settings for agent-specific tooling. This is because they are handled separately and automatically. See the Building Tools for Agents section below for more information.

To see a full example configuration file, refer to the example agent config file.

2. Define the Instructions

At their heart, agents function similarly to roles in that they tell the model how to behave. Agent configuration files have the following settings for the instruction definitions:

dynamic_instructions:     # Whether to use dynamically generated instructions for the agent; if false, static instructions are used. False by default.
instructions:             # Static instructions for the LLM; These are ignored if dynamic instructions are used
variables:                # An array of optional variables that the agent expects and uses

Static Instructions

By default, Coyote agents use statically defined instructions. Think of them as being identical to the instructions for a role, because they virtually are.

Example:

instructions: |
  You are an AI agent designed to demonstrate agentic capabilities

Just like roles, agents support variable interpolation at runtime. There's two types of variables that can be interpolated into the instructions at runtime: special variables (like roles have), and user-defined variables. Just like roles, variables are interpolated into your instructions anywhere Coyote sees the {{variable}} syntax.

Special Variables

The following special variables are provided by Coyote at runtime and can be injected into your agent's instructions:

Name Description Example
__os__ Operating system name linux
__os_family__ Operating system family unix
__arch__ System architecture x86_64
__shell__ The current user's default shell bash
__locale__ The current user's preferred language and region settings en-US
__now__ Current timestamp in ISO 8601 format 2025-11-07T10:15:44.268Z
__cwd__ The current working directory /tmp
__tools__ A list of the enabled tools (global + mcp servers + agent-specific)

User-Defined Variables

Agents also support user-defined variables that can be interpolated into the instructions, and are made available to any agent-specific tools you define (see Building Tools for Agents for more details on how to create agent-specific tooling).

The variables setting in an agent's config has the following fields:

Field Required Description
name * The name of the variable
description * The description of the field
default A default value for the field. If left undefined, the user will be prompted for a value at runtime

Variable values can be supplied three ways (highest precedence first):

  1. At spawn time: A parent agent passes them via agent__spawn's / agent__task_create's variables parameter (see Passing Agent Variables at Spawn). Spawned child agents also inherit the parent's CLI-set variables by name as a fallback.
  2. On the CLI: coyote -a my-agent --agent-variable <name> <value> "...".
  3. Declared default: Used when nothing else supplies a value. A required variable (no default) with no supplied value triggers an interactive prompt at startup, except for spawned child agents, which never prompt (see below).

These variables can be referenced in both the agent's instructions, and in the tool definitions via LLM_AGENT_VAR_<name>.

Example:

instructions: |
  You are an agent who answers questions about a user's system.

  <tools>
  {{__tools__}}
  </tools>

  <system>
  os: {{__os__}}
  os_family: {{__os_family__}}
  arch: {{__arch__}}
  shell: {{__shell__}}
  locale: {{__locale__}}
  now: {{__now__}}
  cwd: {{__cwd__}}
  </system>

  <user>
  username: {{username}}
  </user>
variables:
  - name: username                 # Accessible from the tool definitions via the `LLM_AGENT_VAR_USERNAME` environment variable
    description: Your user name

Dynamic Instructions

Sometimes you may find it useful to dynamically generate instructions on startup. Whether that be via a call to Coyote itself to generate them, or by some other means. Coyote supports this type of behavior using a special function defined in your agents/my-agent/tools.py, agents/my-agent/tools.sh, or agents/my-agent/tools.ts.

Example: Instructions for a JSON-reader agent that specializes on each JSON input it receives agents/json-reader/tools.py:

import json
from pathlib import Path
from genson import SchemaBuilder

def _instructions():
    """Generates instructions for the agent dynamically"""
    value = input("Enter a JSON file path OR paste raw JSON: ").strip()
    if not value:
        raise SystemExit("A file path or JSON string is required.")

    p = Path(value)
    if p.exists() and p.is_file():
        json_file_path = str(p.resolve())
        json_text = p.read_text(encoding="utf-8")
    else:
        try:
            json.loads(value)
        except json.JSONDecodeError as e:
            raise SystemExit(f"Input is neither a file nor valid JSON.\n{e}")
        json_file_path = "<provided-inline-json>"
        json_text = value

    try:
        data = json.loads(json_text)
    except json.JSONDecodeError as e:
        raise SystemExit(f"Provided content is not valid JSON.\n{e}")

    builder = SchemaBuilder()
    builder.add_object(data)
    json_schema = builder.to_schema()
    return f"""
        You are an AI agent that can view and filter JSON data with jq.
        
        ## Context
        json_file_path: {json_file_path}
        json_schema: {json.dumps(json_schema, indent=2)}
    """

or

agents/json-reader/tools.sh:

#!/usr/bin/env bash
set -e

# @meta require-tools jq,genson
# @env LLM_OUTPUT=/dev/stdout The output path

# @cmd Generates instructions for the agent dynamically
_instructions() {
	read -r -p "Enter a JSON file path OR paste raw JSON: " value
	
	if [[ -z "${value}" ]]; then
		echo "A file path or JSON string is required" >&2
		exit 1
	fi 
	json_file_path=""
    inline_temp=""
    cleanup() {
      [[ -n "${inline_temp:-}" && -f "${inline_temp}" ]] && rm -f "${inline_temp}"
    }
    trap cleanup EXIT
    
    if [[ -f "${value}" ]]; then
      json_file_path="$(realpath "${value}")"
      if ! jq empty "${json_file_path}" >/dev/null 2>&1; then
        echo "Error: File does not contain valid JSON: ${json_file_path}" >&2
        exit 1
      fi
    else
      inline_temp="$(mktemp)"
      printf "%s" "${value}" > "${inline_temp}"
      if ! jq empty "${inline_temp}" >/dev/null 2>&1; then
        echo "Error: Input is neither a file nor valid JSON." >&2
        exit 1
      fi
      json_file_path="<provided-inline-json>"
    fi
    
    source_file="${json_file_path}"
    if [[ "${json_file_path}" == "<provided-inline-json>" ]]; then
      source_file="${inline_temp}"
    fi
    
    json_schema="$(genson < "${source_file}" | jq -c '.')"
	cat <<EOF >> "$LLM_OUTPUT"
You are an AI agent that can view and filter JSON data with jq.

## Context
json_file_path: ${json_file_path}
json_schema: ${json_schema}
EOF
}

For more information on how to create custom tools for your agent and the structure of the agent/my-agent/tools.sh, agent/my-agent/tools.py, or agent/my-agent/tools.ts files, refer to the Building Tools for Agents section below.

Variables

All the same variable interpolations supported by static instructions is also supported by dynamic instructions. For more information on what variables are available and how to use them, refer to the Special Variables and User-Defined Variables sections above.

3. Initializing RAG

Each agent you create also has a dedicated knowledge base that adds additional context to your queries and helps the LLM answer queries effectively. The documents to load into RAG are defined in the documents array of your agent configuration file:

documents:
  - https://www.ohdsi.org/data-standardization/
  - https://github.com/OHDSI/Vocabulary-v5.0/wiki/**
  - OMOPCDM_ddl.sql       # Relative path to agent (i.e. file lives at '<coyote-config-dir>/agents/my-agent/OMOPCDM_ddl.sql')

These documents use the same syntax as those you'd define when constructing RAG normally. To see all the available types of documents that Coyote supports and how to use custom document loaders, refer to the RAG documentation.

Anytime your agent starts up, it will automatically be using the RAG you've defined here.

The first time an agent starts with documents attached, Coyote offers to build the knowledge base and asks which storage driver to store it with. yaml (the default, and what Coyote has always done) or duckdb, which keeps the vectors and text on disk so a large corpus doesn't have to be read back into memory on every start. The choice is fixed once the knowledge base is built: changing it means removing the agent's built knowledge base and letting it rebuild, which re-embeds every document.

Note

On Linux, duckdb requires a gnu build. Musl builds are statically linked and cannot load DuckDB's extensions, so they skip the prompt and use yaml (details).

When function calling is enabled, an agent with documents also gets the rag__query built-in tool, which lets the LLM run additional retrieval on-demand during a turn (in addition to the up-front injection). Graph agents drive RAG through explicit rag nodes instead and do not receive this tool.

4. Building Tools for Agents

Building tools for agents is virtually identical to building custom tools, with one slight difference: instead of defining a single function that gets executed at runtime (e.g. main for bash tools and run for Python tools), agent tools define a number of subcommands.

Limitations

You can only utilize one of: a bash-based <coyote-config-dir>/agents/my-agent/tools.sh, a Python-based <coyote-config-dir>/agents/my-agent/tools.py, or a TypeScript-based <coyote-config-dir>/agents/my-agent/tools.ts. However, if it's easier to achieve a task in one language vs the other, you're free to define other scripts in your agent's configuration directory and reference them from the main tools file. Any scripts not named tools.{py,sh,ts} will not be picked up by Coyote's compiler, meaning they can be used like any other set of scripts.

It's important to keep in mind the following:

  • Do not give agents the same name as an executable. Coyote compiles the tools for each agent into a binary that it temporarily places on your path during execution. If you have a binary with the same name as your agent, then your shell may execute the existing binary instead of your agent's tools
  • LLM_ROOT_DIR points to the agent's configuration directory. This is where agents differ slightly from normal tools: The LLM_ROOT_DIR environment variable does not point to the functions/tools directory like it does in global tools. Instead, it points to the agent's configuration directory, making it easier to source scripts and other miscellaneous files

.env File Support

When Coyote loads an agent, it will also search the agent's configuration directory for a .env file. If found, all environment variables defined in the file will be made available to the agent's tools.

Python-Based Agent Tools

Python-based tools are defined exactly the same as they are for custom tool definitions. The only difference is that instead of a single run function, you define as many as you like with whatever arguments you like.

Example: agents/my-agent/tools.py

import urllib.request

def get_ip_info():
  """
  Get your IP information
  """
  with urllib.request.urlopen("https://httpbin.org/ip") as response:
    data = response.read()
    return data.decode('utf-8')

def get_ip_address_from_aws():
    """
    Find your public IP address using AWS
    """
    with urllib.request.urlopen("https://checkip.amazonaws.com") as response:
        data = response.read()
        return data.decode('utf-8')

Coyote automatically compiles these as separate functions for the LLM to call. No extra work is needed. Just make sure you follow all the same steps to define each function as you would when creating custom Python tools.

For more information on how to build tools in Python, refer to the custom Python tools documentation

Bash-Based Agent Tools

Bash-based agent tools are virtually identical to custom bash tools, with only one difference. Instead of defining a single entrypoint via the main function, you actually define as many subcommands as you like.

Example: agents/my-agent/tools.sh

#!/usr/bin/env bash

# @env LLM_OUTPUT=/dev/stdout The output path
# @describe Discover network information about your computer and its place in the internet

# Use the `@cmd` annotation to define subcommands for your script.
# @cmd Get your IP information
get_ip_info() {
  curl -fsSL https://httpbin.org/ip >> "$LLM_OUTPUT"
}

# @cmd Find your public IP address using AWS
get_ip_address_from_aws() {
  curl -fsSL https://checkip.amazonaws.com >> "$LLM_OUTPUT"
}

To compile the script so it's executable and testable:

$ coyote --build-tools

Then you can execute your script (assuming your current working directory is agents/my-agent):

$ ./tools.sh get_ip_info
$ ./tools.sh get_ip_address_from_aws

All other special annotations (@env, @arg, @option @flags) apply to subcommands as well, so be sure to follow the same syntax ad formatting as is used to create custom bash tools globally.

For more information on how to write, build and test tools in bash, refer to the custom bash tools documentation.

TypeScript-Based Agent Tools

TypeScript-based agent tools work exactly the same as TypeScript global tools. Instead of a single run function, you define as many exported functions as you like. Non-exported functions are private helpers and are invisible to the LLM.

Example: agents/my-agent/tools.ts

/**
 * Get your IP information
 */
export async function get_ip_info(): Promise<string> {
  const resp = await fetch("https://httpbin.org/ip");
  return await resp.text();
}

/**
 * Find your public IP address using AWS
 */
export async function get_ip_address_from_aws(): Promise<string> {
  const resp = await fetch("https://checkip.amazonaws.com");
  return await resp.text();
}

// Non-exported helper — invisible to the LLM
function formatResponse(data: string): string {
  return data.trim();
}

Coyote automatically compiles each exported function as a separate tool for the LLM to call. Just make sure you follow the same JSDoc and parameter conventions as you would when creating custom TypeScript tools.

TypeScript agent tools also support dynamic instructions via an exported _instructions() function:

import { readFileSync } from "fs";

/**
 * Generates instructions for the agent dynamically
 */
export function _instructions(): string {
  const schema = readFileSync("schema.json", "utf-8");
  return `You are an AI agent that works with the following schema:\n${schema}`;
}

For more information on how to build tools in TypeScript, refer to the custom TypeScript tools documentation.

5. Conversation Starters

It's often helpful to also have some conversation starters so users know what kinds of things the agent is capable of doing. These are available in the REPL via the .starter command and are selectable.

They are defined using the conversation_starters setting in your agent's configuration file:

Example: agents/my-agent/config.yaml:

conversation_starters:
  - What is my username?
  - What is my current shell?
  - What is my ip?
  - How much disk space is left on my PC??
  - How to create an agent?

Example Conversation Starters

6. Todo System & Auto-Continuation

Coyote includes a built-in task tracking system designed to improve the reliability of LLM interactions, especially when using smaller language models. The Todo System helps models:

  • Break complex tasks into manageable steps
  • Track progress through multi-step workflows
  • Automatically continue work until all tasks are complete

Quick Configuration

# agents/my-agent/config.yaml
auto_continue: true              # Enable auto-continuation
max_auto_continues: 10           # Max continuation attempts
inject_todo_instructions: true   # Include the default todo instructions into prompt
continuation_prompt: null        # Custom prompt used when auto-continuing if inject_todo_instructions is 'false'

How It Works

  1. When inject_todo_instructions is enabled, agents receive instructions on using five built-in tools:

    • todo__init: Initialize a todo list with a goal
    • todo__add: Add a task to the list
    • todo__done: Mark a task complete
    • todo__list: View current todo state
    • todo__clear: Clear the entire todo list and reset the goal

    These instructions are a reasonable default that detail how to use Coyote's To-Do System. If you wish, you can disable the injection of the default instructions and specify your own instructions for how to use the To-Do System into your main instructions for the agent.

  2. When auto_continue is enabled and the model stops with incomplete tasks, Coyote automatically sends a continuation prompt with the current todo state, nudging the model to continue working.

  3. This continues until all tasks are done or max_auto_continues is reached.

When to Use

  • Multistep tasks where the model might lose track
  • Smaller models that need more structure
  • Workflows requiring guaranteed completion of all steps

For complete documentation including all configuration options, tool details, and best practices, see the Todo System Guide.

7. Sub-Agent Spawning System

Coyote agents can spawn and manage child agents that run in parallel as background tasks inside the same process. This enables orchestrator-style agents that delegate specialized work to other agents, similar to how tools like Claude Code or OpenCode handle complex multi-step tasks.

For a working example of an orchestrator agent that uses sub-agent spawning, see the built-in sisyphus agent. For an example of the teammate messaging pattern with parallel sub-agents, see the domain-reviewer agent.

Jobs vs. sub-agents: sub-agents are for work that needs reasoning: they run a full LLM loop. To background a single long-running tool call (a build, a test suite, a slow MCP invocation), use the Background Jobs system (job__* tools) instead. The two compose one way only: agents may start jobs, but a job can never start an agent or another job. Completion notifications (system_notifications entries on the next tool result) cover both systems.

Spawning Configuration

Setting Type Default Description
can_spawn_agents boolean false Enable this agent to spawn child agents
spawnable_agents list of strings unset Whitelist of agent names this agent may spawn. Omit for unrestricted access.
max_concurrent_agents integer 4 Maximum number of child agents that can run simultaneously
max_agent_depth integer 3 Maximum nesting depth for sub-agents (prevents runaway spawning chains)
inject_spawn_instructions boolean true Inject the default spawning instructions into the agent's system prompt
summarization_model string current model Model to use for summarizing long sub-agent output (e.g. openai:gpt-4o-mini)
summarization_threshold integer 4000 Character count above which sub-agent output is summarized before returning
escalation_timeout integer 0 Seconds a sub-agent waits for an escalated user interaction response; 0 = wait indefinitely (default)

Example configuration:

# agents/my-orchestrator/config.yaml
can_spawn_agents: true
spawnable_agents:
  - explore
  - coder
  - oracle
max_concurrent_agents: 6
max_agent_depth: 2
inject_spawn_instructions: true
summarization_model: openai:gpt-4o-mini
summarization_threshold: 3000
escalation_timeout: 600

Restricting which agents can be spawned (spawnable_agents)

By default (i.e. when spawnable_agents is omitted), any agent installed under <coyote-config-dir>/agents/ is spawnable.

To restrict, add a list of agent names. Only agents whose directory name appears in the list will be spawnable. Anything else the agent tries to spawn via agent__spawn is rejected with an actionable error, and hidden from agent__list_available output.

can_spawn_agents: true
spawnable_agents:
  - explore
  - coder
  - oracle

Use this to:

  • Scope an orchestrator to a focused set of specialists. An orchestrator that only needs explore/coder/oracle won't accidentally spawn unrelated personal agents in your config directory.
  • Enforce team boundaries. In a shared/CI setup, restrict what a given agent is allowed to invoke.
  • Prevent recursion cycles. Combined with max_agent_depth, an explicit whitelist gives you fine-grained control over the spawn graph.

Notes:

  • Match is exact and case-sensitive. Use directory names as they appear on disk.
  • spawnable_agents: [] means literally nothing spawnable (rare but valid).
  • Graph agents (with a graph.yaml) always ignore spawnable_agents; they statically declare their spawn targets via agent nodes in the graph itself.
  • Override at runtime via env var: <AGENT_NAME>_SPAWNABLE_AGENTS as a JSON array (e.g. SISYPHUS_SPAWNABLE_AGENTS='["explore","coder"]').

Spawning & Collecting Agents

When can_spawn_agents is enabled, the agent receives tools for spawning and managing child agents:

Tool Description
agent__spawn Spawn a child agent in the background, optionally passing its declared variables. Returns an agent ID immediately.
agent__check Non-blocking check: is the agent done? Returns PENDING or the result.
agent__collect Blocking wait: wait for an agent to finish, return its output.
agent__list_available List all agent types installed and available to spawn (name + description + declared variables). Discovery counterpart to agent__spawn.
agent__list_running List all subagents you have spawned, with their status.
agent__cancel Cancel a running agent by ID.

The core pattern is Spawn -> Continue -> Collect:

# 1. Spawn agents in parallel (returns IDs immediately)
agent__spawn --agent explore --prompt "Find auth middleware patterns in src/"
agent__spawn --agent explore --prompt "Find error handling patterns in src/"

# 2. Continue your own work while they run

# 3. Check if done (non-blocking)
agent__check --id agent_explore_a1b2c3d4

# 4. Collect results when ready (blocking)
agent__collect --id agent_explore_a1b2c3d4
agent__collect --id agent_explore_e5f6g7h8

Any agent defined in your <coyote-config-dir>/agents/ directory can be spawned as a child. Child agents:

  • Run in a fully isolated environment (separate session, config, and tools)
  • Have their output suppressed from the terminal (no spinner, no tool call logging)
  • Return their accumulated output to the parent when collected

Passing Agent Variables at Spawn

agent__spawn accepts an optional variables parameter (an object of string values). This is the spawn-time equivalent of the CLI's --agent-variable:

agent__spawn --agent pr-reviewer --variables {"pr": "1234"} --prompt "Review this PR."

Discovering an agent's variables. agent__list_available advertises each agent's declared variables, so a parent can learn the spawn contract up front:

{
  "name": "pr-reviewer",
  "description": "Reviews pull requests",
  "variables": [
    { "name": "pr", "description": "The PR URL or number", "required": true }
  ]
}

required is true when the variable declares no default; the variables key is omitted for agents that declare none.

Precedence. For each declared variable, the value is resolved in this order:

  1. The spawn call's variables entry
  2. A same-named variable inherited from the parent (e.g. set on the parent via --agent-variable)
  3. The variable's declared default

Validation and error behavior. Unknown variable names, non-string values, or passing variables to an agent that declares none all return a self-correcting error listing the target agent's declared variables. Spawned children never trigger the interactive variable prompt: if a required variable ends up with no value, the spawn fails with an error naming each missing variable so the parent can re-spawn with the right variables.

Notes:

  • Values reach the child's instructions ({{name}} interpolation), its tools (LLM_AGENT_VAR_<NAME>), and, for graph agents, the initial graph state, so {{name}} resolves inside llm node prompts.
  • If the target agent is configured with a persistent agent_session and an existing session is resumed, the session's stored variables win and spawn-provided variables are ignored.
  • agent__task_create accepts the same variables parameter for auto-dispatched tasks (see Active Task Dispatch).

Task Queue with Dependencies

For complex workflows where tasks have ordering requirements, the spawning system includes a dependency-aware task queue:

Tool Description
agent__task_create Create a task with optional dependencies, auto-dispatch agent, and agent variables.
agent__task_list List all tasks with their status, dependencies, and assignments.
agent__task_complete Mark a task done. Returns newly unblocked tasks and auto-dispatches agents.
agent__task_fail Mark a task as failed. Dependents remain blocked.
# Create tasks with dependency ordering
agent__task_create --subject "Explore existing patterns"
agent__task_create --subject "Implement feature" --blocked_by ["task_1"]
agent__task_create --subject "Write tests" --blocked_by ["task_2"]

# Mark tasks complete to unblock dependents
agent__task_complete --task_id task_1

Active Task Dispatch

Tasks can optionally specify an agent to auto-spawn when the task becomes runnable:

agent__task_create \
  --subject "Implement the auth module" \
  --blocked_by ["task_1"] \
  --agent coder \
  --variables {"project_dir": "/path/to/repo"} \
  --prompt "Implement auth module based on patterns found in task_1"

When task_1 completes and the dependent task becomes unblocked, an agent is automatically spawned with the specified prompt, and with the task's stored variables passed through to the spawn, exactly as if they had been given to agent__spawn directly (same precedence and validation). agent__task_list echoes each task's variables alongside its prompt. No manual intervention needed. This enables fully automated multi-step pipelines.

Output Summarization

When a child agent produces long output, it can be automatically summarized before returning to the parent. This keeps parent context windows manageable.

  • If the output exceeds summarization_threshold characters (default: 4000), it is sent through an LLM summarization pass
  • The summarization_model setting lets you use a cheaper/faster model for summarization (e.g. gpt-4o-mini)
  • If summarization_model is not set, the parent's current model is used
  • The summarization preserves all actionable information: code snippets, file paths, error messages, and concrete recommendations

Teammate Messaging

All agents (including children) automatically receive tools for direct sibling-to-sibling messaging:

Tool Description
agent__send_message Send a text message to another agent's inbox by ID.
agent__check_inbox Drain all pending messages from your inbox.

This enables coordination patterns where child agents share cross-cutting findings:

# Agent A discovers something relevant to Agent B
agent__send_message --id agent_reviewer_b1c2d3e4 --message "Found a security issue in auth.rs line 42"

# Agent B checks inbox before finalizing
agent__check_inbox

Messages are routed through the parent's supervisor. A parent can message its children, and children can message their siblings. For a working example of the teammate pattern, see the built-in domain-reviewer agent, which spawns file-specific reviewers that share cross-cutting findings with each other.

Sub-agents run by graph agent nodes can also form per-fan-out teams: set teammates: true on the agent node and concurrent siblings (map branches or same-super-step flagged nodes) get pre-provisioned inboxes, a roster block in their prompts, and a peers section in agent__list_running. See Teammate messaging in fan-outs.

Runaway Safeguards

The spawning system includes built-in safeguards to prevent runaway agent chains:

  • max_concurrent_agents: Caps how many agents can run at once (default: 4). Spawn attempts beyond this limit return an error asking the agent to wait or cancel existing agents.
  • max_agent_depth: Caps nesting depth (default: 3). A child agent spawning its own child increments the depth counter. Attempts beyond the limit are rejected.
  • can_spawn_agents: Only agents with this flag set to true can spawn children. By default, spawning is disabled. This means child agents cannot spawn their own children unless you explicitly create them with can_spawn_agents: true in their config.

8. User Interaction Tools

Coyote includes built-in tools for agents (and the REPL) to interactively prompt the user for input. These tools are always available. No configuration needed. They are automatically injected into every agent and into REPL mode when function calling is enabled.

User Interaction Available Tools

Tool Description Returns
user__select Present a list of named options and ask the user to pick exactly one. Use this — not confirm — whenever there are 2+ named options to choose between. The selected option string
user__confirm Ask a genuinely binary yes/no question with no other choices. Do NOT use for "A or B?" situations; use select instead. "yes" or "no"
user__input Collect free-form text from the user when no predefined options exist. The text entered by the user
user__checkbox Ask the user to pick one or more options from a list (multi-select). Use when multiple answers are valid simultaneously. Array of selected option strings

Parameters:

  • user__select: --question "..." --options ["Option A", "Option B", "Option C"]
  • user__confirm: --question "..."
  • user__input: --question "..."
  • user__checkbox: --question "..." --options ["Option A", "Option B", "Option C"]

At the top level (depth 0), these tools render interactive terminal prompts directly using arrow-key navigation, checkboxes, and text input fields.

Escalation (Sub-Agent to User)

When a child agent (depth > 0) calls a user__* tool, it cannot prompt the terminal directly. Instead, the request is automatically escalated to the root agent:

  1. The child agent calls user__select(...) and blocks, waiting for a reply
  2. The root agent sees a pending_escalations notification in its next tool results
  3. The root agent either answers from context or prompts the user itself, then calls agent__reply_escalation to unblock the child
  4. The child receives the reply and continues

The escalation wait is configurable via escalation_timeout in the agent's config.yaml (default: 0 = wait indefinitely, so autonomous runs never lose an approval while the user is away). When a nonzero timeout is configured and expires, the child receives a fallback message asking it to use its best judgment.

Tool Description
agent__reply_escalation Reply to a pending child escalation, unblocking the waiting child agent.

This tool is automatically available to any agent with can_spawn_agents: true.

9. Skills

Skills are modular knowledge or capability packs that the model loads and unloads mid-conversation via skill__list and skill__load. Where a role defines who the assistant is, a skill layers a methodology (code-review), a toolkit (git-master), or a one-shot helper onto whatever role/agent/session is active. Multiple skills can be loaded at once; their instructions stack and their granted tools/MCP servers union.

Agents can override the global skill policy in their own config.yaml:

# agents/my-agent/config.yaml
skills_enabled: true             # Master switch for this agent (false wins at any level; unset inherits global)
enabled_skills:                  # Allowlist for this agent (most-specific-wins: agent > role > global)
  - code-review
  - git-master
inject_skill_instructions: true  # Inject the skill-discovery hint into this agent's system prompt
skill_instructions: null         # Override the built-in hint text (null uses the default)
  • skills_enabled (default unset): Setting false disables skills for this agent. skill__list, skill__load, and skill__unload are not exposed when this agent runs. If unset, the agent inherits the global setting.
  • enabled_skills (default unset): When set, restricts which skills this agent can load. Skills not in this list are filtered out of skill__list, and skill__load rejects them with "Skill 'X' is not enabled in this context". If unset, the agent inherits the role or global allowlist. Accepts a YAML list or a comma-separated string.
  • inject_skill_instructions (default true): Controls whether Coyote appends a short hint to the system prompt telling the model to call skill__list early in a task. Suppressed automatically when the effective enabled_skills set is empty.
  • skill_instructions (default unset): Replaces the built-in hint text with your own wording.

Skills require function calling (function_calling_support: true); the skill subsystem is silently disabled otherwise. For the full skills model, including the frontmatter format, validation rules, built-in skills, and the graph-agent variant, see the Skills Guide.

For working examples of agents that use skills heavily, see the bundled file-reviewer and domain-reviewer agents.

10. Auto-Injected Prompts

Coyote automatically appends usage instructions to your agent's system prompt for each enabled built-in system. These instructions are injected into both static and dynamic instructions after your own instructions, ensuring agents always know how to use their available tools.

System Injected When Toggle
Todo tools auto_continue: true AND inject_todo_instructions: true inject_todo_instructions
Spawning tools can_spawn_agents: true AND inject_spawn_instructions: true inject_spawn_instructions
Teammate messaging Always (all agents) None (always injected)
User interaction Always (all agents) None (always injected)
Skill discovery hint skills_enabled: true AND inject_skill_instructions: true AND effective enabled_skills is non-empty inject_skill_instructions

If you prefer to write your own instructions for a system, set the corresponding inject_* flag to false and include your custom instructions in the agent's instructions field. The built-in tools will still be available; only the auto-injected prompt text is suppressed.

Built-In Agents

Coyote comes packaged with some useful built-in agents:

  • adversary: A graph-based adversarial plan-conformance reviewer. Where code-reviewer asks "is this code good?", adversary asks "is this the code the plan asked for? All of it, and only it?". The graph extracts the plan's acceptance criteria into a list and fans out one fresh-context verification branch per criterion, so partial coverage ("checked 8 of 12 and waved the rest through") is structurally impossible. Each verdict passes a deterministic contract gate: MET requires evidence including the test proving the behavior (no test means at best PARTIAL), malformed output is rejected once then recorded as PARTIAL (unproven). Then, a holistic ADDITIVE-only pass hunts what per-criterion checks can't see: absence ("the dog that didn't bark"), scope drift, interface substitution, silently-overridden recorded decisions, and gamed tests. A script computes the blocking ADVERSARIAL_REVIEW: CONFORMS/DIVERGES verdict: CONFORMS requires every criterion MET with zero holistic complaints, and a missing plan fails closed. The post-implementation counterpart to oracle's pre-implementation plan-review. Designed to be delegated to by sisyphus alongside code-reviewer (they cover different failure modes: quality vs. conformance).
  • architecture-reviewer: An on-demand architecture improvement scout (via the codebase-design skill). Scans a codebase for deepening opportunities (e.g. shallow modules, leaked seams, missing locality, etc.), weighted by git-history hot spots, presents candidates as a visual HTML (or markdown) report, then refines the chosen candidate into an implementation-ready interface proposal via design-it-twice. Proposes only, never implements, and is NOT a completion gate: invoke it when you want the codebase made deeper, more testable, and easier to navigate.
  • architect: A design-doc orchestrator for large-scale implementation jobs. Consumes a high-level design doc, decomposes it into a quality-gated plan (gatekeeper self-containedness gate + oracle plan-review) and ~1-engineer-day task files (via the design-session and task-tracking skills, tracked on disk in a plans/ directory), spawns one sisyphus per task on a single run branch with a per-task review-gauntlet done-gate (forced adversary conformance lane, plus probe when the task changes consumer-facing surface), and finishes with ONE draft PR, CI checks watched to green, plus follow-up task files for every manual action the code can't do for itself. Ends with a whetstone continuous-improvement pass when the run addressed review feedback from outside its own lanes. An escalation_policy variable governs decision points: autonomous answers them (its own and its Sisyphus children's escalations) from standing rulings in <config_dir>/share/standing-rulings.md or a clearly recommended option, amends plan text before any conformance re-run, and batches every self-made call into a Decisions taken autonomously digest in the final report and PR body: secrets, money movement, and destructive actions always escalate to you. Supports opt-in worktree-based parallel task execution. Plans declare a quality bar: rigor (poc/prototype/production) plus the surfaces being built (rest-api, cli, library, worker, iac, db-migration, frontend, ci-cd, or other:<label> via a design-time librarian lookup), which flows into every downstream reviewer, with an evidence-cited rejection protocol for convention findings. When a design hinges on deep external unknowns, it escalates research from a librarian lookup to a full deep-research spawn (always with autonomy: autonomous, so the child never stalls on its approval gate).
  • coder: An agent to assist you with all your coding tasks
  • code-reviewer: A CodeRabbit-style graph-based review orchestrator. This is the deterministic shell around LLM review judgment. Scripts resolve the diff, the quality bar (rigor + surfaces: caller-passed, read from the active plan's frontmatter, or detected from the diff), repo conventions, matching review-miss ledger patterns, and repo-history signals (fix/revert clusters plus prior PR review comments on fragile paths); domain linters (tflint, hadolint, actionlint, buf breaking) run unconditionally when installed. Changed files are grouped into DOMAIN slices with deterministic proposal, LLM refinement, and an exact-cover gate so no file can be lost, and each slice is reviewed in parallel by a domain-reviewer leader with peer messaging between leaders; every leader report passes a completeness gate (mandatory sections present even when clean, reject-and-retry once). A synthesis node with NO verdict authority merges findings, finding-verifier re-validates every 🔴/🟡 on an unskippable graph edge, and a SCRIPT computes the rigor folding (below-threshold [convention] findings defer; 🔴 never folds) and the MERGE-READY/NEEDS-HUMAN verdict with deterministic always-human triggers (destructive migrations, auth surface) — the model that wrote the findings never grades its own homework. Optional lanes: operational history (prior_art_agent), org context (org_context_agent), and a downstream-consumers sweep (consumers_root/github_org).
  • demo: An example agent to use for reference when learning to create your own agents
  • deep-research: A graph-based deep-investigation agent for questions that deserve hours, not minutes. Plans the investigation, decomposes it into research questions, and fans each question out to its own librarian running at research_depth: deep, then vets the combined sources (dead links, paywalled citations) and runs a critique -> re-research reflexion loop until the critique passes or the reflexion_budget variable (default 2) is spent; raise it to let the report churn longer. An autonomy variable governs the final gate: supervised (default) pauses for your approval and feedback on the report; autonomous skips the human gate and returns the report plus the source check. Set it whenever it's spawned as a subagent so an unattended run never parks on an approval prompt. Designed to be delegated to by sisyphus and architect as the top rung of the research ladder: librarian (standard) -> librarian (deep) -> deep-research.
  • domain-reviewer: A domain-slice review leader (used by the code-reviewer graph). Where file-reviewer reviews one file in isolation, domain-reviewer reviews a group of RELATED changed files (e.g. the DB migration plus the queries that use it, the routes plus their handlers, etc.) as one coherent unit: guard symmetry across the slice's sibling paths, literal/enum drift between files, schema <-> usage mismatch, and slice-level blast-radius / test-adequacy / removed-guard checks reported even when clean. Small slices are reviewed directly with the full skill stack; larger ones fan out one file-reviewer per file with a sibling roster. Leaders run as parallel map branches with teammate messaging armed, so the DB leader can warn the API leader about a renamed column mid-review. Emits a machine-checked report contract ending in DOMAIN_REVIEW_COMPLETE.
  • explore: An agent designed to help you explore and understand your codebase
  • file-reviewer: An agent designed to perform code-review on a single file (used by domain-reviewer inside the code-reviewer graph). Reviews with the code-review and ai-slop-remover skills, and additionally loads the transactional-integrity skill when the diff touches state-changing code (e.g. DB writes, transactions, queue/webhook/job handlers, retries, or external side effects, etc.) to catch atomicity gaps, read-modify-write races, non-idempotent handlers of at-least-once inputs, and dual-writes with no reconciliation. Also loads logging-discipline on diffs with operational surface, and, when the orchestrator's surface routing names them, the surface-contract review skills (rest-api-review, cli-review, library-review, worker-review, iac-review, migration-review, cicd-review), whose findings carry [convention]/[correctness] markers used for rigor folding and the evidence-cited rejection protocol downstream.
  • finding-verifier: A graph-based fact-checker for code-review findings (wired into the code-reviewer graph as an unskippable edge). Maps over a review's 🔴/🟡 findings in parallel, fresh context per finding, so the verifier inherits none of the reviewer's assumptions, re-reads the cited code, and returns VERIFIED (with quoted evidence), FALSE (only with proof, e.g. the "missing" guard exists at another path:line), or UNVERIFIABLE (kept, marked). Each branch's verdict passes a deterministic contract gate (machine-validated JSON, authoritative id stamped from the finding itself, retry once; malformed output records UNVERIFIABLE, so a bad branch never sinks the run). It never re-judges severity. It only tests whether a claim is true. code-reviewer uses the verdicts to drop provably-false findings before the final report; dropped findings are tallied, never silently vanished.
  • gatekeeper: A plan self-containedness gate (via the plan-gatekeeping skill). Audits a plan against the "sealed container" standard, meaning every question a context-free implementer will hit is either answered inline or delegated via a VERIFIED pointer to the exact code/docs that answer it (where infra code goes, what DB tech, which layout to mirror, exact test commands, how to boot the service locally from a clean state), and returns a blocking PLAN_GATE: SEALED/LEAKY verdict with the missing questions. The pre-implementation context counterpart to plan-review (executability) and adversary (post-implementation conformance). Designed to be delegated to by architect.
  • librarian: A graph-based agent that researches external references. It finds official docs, production OSS examples, and web best practices. The "external grep" sibling of explore (which handles internal/codebase grep). Designed to be delegated to by sisyphus whenever an unfamiliar library, API, or framework is involved. A research_depth variable (standard/deep) sets the effort ceiling: deep roughly triples the search/OSS-example/fetch budgets and the source quota (and extends the graph timeout to match) for exhaustive coverage; the mode deep-research uses for every one of its research lanes.
  • oracle: An agent for high-level architecture, design decisions, complex debugging, and reviewing implementation plans before execution (via the plan-review skill, returning a PLAN_REVIEW: OKAY/REJECT verdict)
  • probe: A black-box usage-pattern verifier (via the usage-pattern-testing skill). Where every other review gate reads text, probe verifies behavior: it boots the changed code locally from a clean, isolated state and exercises the consumer-facing surface (HTTP APIs, RPCs, CLIs) as a real cold-start consumer. Runs the repo's existing usage suites first (regression check), derives expected behaviors from the SPEC, never the implementation, so the implementer's misreadings can't become its assertions, and authors tests for uncovered patterns in the repo's suite conventions (tools like Hurl/curl/grpcurl are examples, not requirements). Returns a blocking USAGE_PROBE: PASS/FAIL/INCONCLUSIVE verdict; its tests are deliverables adopted as permanent regression coverage. Designed to be delegated to by sisyphus and architect when a change touches consumer-visible surface.
  • report-writer: An agent to polish research findings into clear, citation-preserving final reports
  • review-gauntlet: A graph-based "done gate" that runs the whole review stack as ONE spawn. A script derives deterministic change signals (auth surface, dependency/migration/exec changes, consumer-facing surface), an LLM node may ADD lanes but never remove them, and a rules floor guarantees the minimum panel: code-reviewer always, adversary whenever plan context exists, security-reviewer on security-relevant signals, and probe when consumer surface changed and a local-run recipe exists. Lanes run in parallel with verdict independence (no teammate messaging between reviewers), each lane's sentinel is machine-parsed (a missing or malformed verdict BLOCKS, it never passes), and a script computes the final GAUNTLET: PASS/BLOCKED verdict (probe INCONCLUSIVE blocks with an environment note, never coerced to pass or fail). The preferred way for sisyphus and architect to run the review stack.
  • security-reviewer: A security analyst for code changes (via the security-review skill). Traces untrusted data from sources to dangerous sinks (injection, committed secrets, authn/authz gaps, path traversal, SSRF, unsafe deserialization, supply chain), then returns a posture-gated SECURITY_REVIEW: PASS/FAIL verdict. The security_posture variable (prototype/standard/hardened) sets the blocking threshold so POCs aren't held to production strictness, while Critical findings (leaked credentials, host-endangering code) block in every posture. Runs a mechanized pre-pass first (gitleaks/semgrep/dependency audits when already installed) whose hits are leads to trace, never pasted findings. Designed to be delegated to by sisyphus alongside code-reviewer and adversary.
  • sisyphus: A powerhouse orchestrator agent for writing complex code and acting as a natural language interface for your codebase (similar to ClaudeCode, Gemini CLI, Codex, or OpenCode). Uses sub-agent spawning to delegate to explore, librarian, deep-research, coder, oracle, review-gauntlet, code-reviewer, adversary, security-reviewer, probe, step-runner, and whetstone. On non-trivial work it runs the review stack, preferably as ONE review-gauntlet spawn (the done gate that machine-parses every lane's verdict), else as up to four individual review passes: code-reviewer for code quality, adversary for plan conformance, and security-reviewer for exploitability when the change touches attack surface, and probe for black-box usage-pattern verification when the change touches consumer-facing surface. After a run that addressed review feedback from outside its own lanes (humans, or a teammate's independent review agent), it spawns whetstone once to fold the review misses back into the suite as user-approved improvements. An escalation_policy variable governs mid-run decisions: autonomous resolves them from standing rulings (<config_dir>/share/standing-rulings.md, recorded via the record-ruling macro) or a clearly recommended option, amends plan/criteria text before any re-review, and reports every self-made call in a Decisions taken autonomously digest: secrets, money movement, and destructive actions always escalate. Also supports plan-driven workflows: authoring phased implementation plans (via the plan-authoring skill), having oracle review them, and executing them one reviewed step at a time. Handles review findings quality-bar-aware: the plan's rigor calibrates which severities block (🔴 always does) and maps to a default security_posture; below-threshold [convention] findings defer into follow-ups instead of blocking; and a convention finding can be rejected only with cited evidence (a repo convention at file:line or a recorded plan decision). Never 🔴 or [correctness] findings.
  • sql: A universal SQL agent that enables you to talk to any relational database in natural language
  • step-runner: A graph-based agent that executes ONE step of a phased implementation plan (a plans/ repo authored with the plan-authoring skill) with the step protocol enforced as graph edges: orient from the previous handoff -> staleness-check the plan -> implement (delegating to coder) -> format/lint/build/full-test verification -> edge-case sweep -> optional independent review (code-reviewer) -> evidence-backed handoff -> hard-stop user approval gate. Returns STEP_COMPLETE/STEP_BLOCKED/STEP_REJECTED/STEP_FAILED to the caller. Designed to be delegated to by sisyphus.
  • whetstone: A continuous-improvement agent for the review suite; the review suite reviews code; whetstone reviews the review. Spawned by sisyphus and architect at the end of a run that addressed review feedback from outside the run's own lanes (humans, or a teammate's independent review agent, never its own suite's output; third-party agent findings count only when the author actually addressed them). Classifies each piece of feedback as CATCH/PARTIAL/MISS against what the suite's own reviewers flagged, then generalizes the misses: taste is dropped, one-offs go to a candidates inbox, org-specific classes become review-miss ledger entries, and general classes are drafted as suite edits in house style. Everything is applied only with user approval, and edits go where the suite lives: a configured suite_repo (then optionally mirrored to the live config, drift-guarded), or directly into the live config with per-file backups when no repo is set. Additive only; it never weakens an existing rule. Proposals are persisted before they are proposed: every surviving draft is written to share/whetstone-pending/<UTC ts>-<owner>-<repo>-<N>.md (one ## P<n> block per proposal, with the quoted evidence and the full remediation text) before the approval prompt, so an unanswered prompt, a headless spawn, or a session without write tools never loses it. Applied and declined blocks are deleted, unanswered ones stay status: pending, and emptied files are removed. To pick them up later run coyote --agent whetstone and say apply pending: that mode skips classification, lists every pending block oldest first, asks which to apply, and routes the approved ones through the normal apply path. A spawner that declares itself headless (e.g. a PR-watch round) gets the persisted file and no prompt.

Coyote writes these built-in agents to your agents directory on first run and never overwrites them afterward, so any edits you make to them are preserved across Coyote updates. To discard your local changes and reinstall the built-in agents from the current Coyote build, run coyote --install agents (or .install agents in the REPL). Agents you created yourself are not affected.

Sandbox Support

If you run Coyote inside a Sandbox, agents that need external binaries or specific network domains must ship a per-agent sbx-mixin.yaml alongside their config.yaml (or graph.yaml). Coyote discovers these automatically on every coyote --sandbox. No flags or registration required.

Layout:

<coyote-config-dir>/agents/<my-agent>/
├── config.yaml
├── tools.sh
├── sbx-mixin.yaml     # <- gets auto-applied alongside the embedded base kit
└── files/             # <- optional sibling: dotfiles/scripts/refs auto-mounted into the sandbox
    └── home/
        └── .config/my-tool/settings.json
        workspace/
        └── .editorconfig

The sibling files/ directory is optional. If present, its contents are staged into the mixin's kit and injected into the sandbox via sbx's static-files convention: files/home/* lands under /home/agent/, files/workspace/* lands under the mounted workspace. See Sandboxes: Bundling static files alongside a mixin for the caveats (symlinks rejected, tree contents hashed into the kit identity, exec bits preserved).

Example

A custom agent that uses httpie to call an internal API:

# <coyote-config-dir>/agents/internal-api-agent/sbx-mixin.yaml
schemaVersion: "2"
kind: mixin
name: agent-internal-api
description: Installs httpie and allows access to our internal API host

permissions:
  network:
    allow:
      - "internal-api.example.com"

setup:
  install:
    - command: |
        sudo apt-get update
        sudo apt-get install -y httpie
      user: "1000"
      description: Install httpie for the internal-api-agent

See Sandboxes: Extending the Sandbox for the full discovery path table and the official sbx mixin reference for the schema.

Sandbox caveats

  • Per-agent mixins are applied on every coyote --sandbox regardless of which agent you invoke. Mixin discovery is global by design (matches Coyote's "everything in the config dir is live" model). Users with many agents pay the install cost for all of their mixins once on first-run; subsequent attaches are instant.
  • Agents that spawn sub-agents need the spawned agents' mixin requirements too. Either co-locate them in the parent agent's mixin or rely on each spawned agent shipping its own; both work.
  • Built-in agents shipped via coyote --install agents may project new sbx-mixin.yaml files into your config on update. Re-running the sandbox after such an install surfaces them in the verbose log with the extra installs/domains they bring. Not a bug, just visibility.
  • The sql agent's usql install is in the base kit, not a per-agent mixin. Same for pandoc (used by fetch_url_via_curl). Both ship with every Coyote sandbox automatically. See assets/sbx-kit/spec.yaml for the full base prereq list.
⚠️ **GitHub.com Fallback** ⚠️