This guide builds a small but complete configuration: a calculator tool, an agent that calls it, and a test that exercises the agent. It mirrors the declarative model end to end — declare resources, reference them with ${kind.ref_name}, then run the pipeline. Everything lives in one file, math.yaml, with resources separated by ---.

1. Declare the tool

A tool is a callable function an agent can invoke. The only schema-required field is permission; to actually run, a tool also needs a binding and a source_path pointing at its implementation.
math.yaml
kind: tool
ref_name: calculator
name: calculator
display_name: Calculator
description: Adds, subtracts, multiplies, and divides two numbers.
permission: read_only
source_path: ./calculator
binding:
  python:
    function: calculator:main
input_schema:
  type: object
  properties:
    operation:
      type: string
      enum: [add, subtract, multiply, divide]
    a:
      type: number
    b:
      type: number
  required: [operation, a, b]
binding.python.function uses module:function format — here, main() in calculator.py. source_path is a directory holding the Python file(s), a schema.yaml, and an optional requirements.txt. Paths are resolved relative to the config file’s directory.

2. Declare the agent

The agent references the tool by ref with ${tool.calculator}. wxctl turns that reference into a dependency edge, so the tool is created before the agent and the agent receives the tool’s real ID at execution time. An agent requires name, description, style, and llm.
math.yaml
---
kind: agent
ref_name: math_assistant
name: math_assistant
display_name: Math Assistant
description: An assistant that performs arithmetic using the calculator tool.
instructions: Use the calculator tool for any arithmetic the user requests.
llm: groq/openai/gpt-oss-120b
style: default
tools:
  - ${tool.calculator}
The llm field accepts a plain model name (no dependency) or a ${model.<ref>} reference to a model resource you also declare. style controls reasoning: default is standard conversational, react enables step-by-step Reasoning + Acting, planner enables multi-step task decomposition.

3. Declare a test

A kind: test resource exercises a deployed agent. Each entry in turns sends a chat message; expect_tools asserts which tools the agent should call, and expect_answer describes the answer to look for. Tests run only under wxctl test — they are ignored by plan, apply, and destroy.
math.yaml
---
kind: test
ref_name: math_smoke_test
agent: ${agent.math_assistant}
turns:
  - message: "What is 2 plus 3?"
    expect_tools:
      - calculator
    expect_answer: "5"

4. Validate, plan, apply, test

1

Validate the schema

Check the file against the resource schemas before touching any service:
wxctl validate -f math.yaml
2

Preview the plan

A dry run — see what would be created, in dependency order, without making changes:
wxctl plan -f math.yaml
3

Apply

Create the tool and the agent remotely:
wxctl apply -f math.yaml
4

Test

Run the test turns against the deployed agent:
wxctl test -f math.yaml
When you are done, wxctl destroy -f math.yaml tears the resources down in reverse-dependency order.

Next steps

Resource kinds

Every kind wxctl supports, with fields and endpoints.

Troubleshooting

Logging, concurrency, and color environment variables.