Your First Agent with wax init
This is the shortest path from an empty directory to a governed agent running on Waxell's runtime. You'll scaffold a manifest, push it, fire it, and read the trace, in about five minutes. You don't write any Python.
You need: the wax CLI (pipx install waxell, see
Quickstart → Install) and a Waxell API key
(wax_sk_…) from Settings → API Keys in the app.
1. Point the CLI at your workspace
wax config init --profile acme
It prompts for the API URL (press Enter for https://api.waxell.dev) and
your API key, then writes the profile to ~/.waxell/config, readable only
by you. To skip the prompts:
wax config init --profile acme --api-url https://api.waxell.dev --api-key wax_sk_... --no-input
Make it the active profile and check that it resolves to the workspace you expect:
wax config use acme
wax whoami
wax whoami prints your email, the workspace name and slug, and its Tenant ID.
To use a profile for a single command without switching, pass -p <profile>, as
in wax -p acme push.
2. Scaffold the agent
mkdir triage && cd triage
wax init
wax init [NAME] names the agent after the directory unless you pass NAME
(the name is lower-cased, and characters other than letters, digits and _
become _). It writes two files: waxell.yaml and a short README.md. This is
the manifest:
# waxell.yaml — the whole deploy.
#
# `wax push` publishes this agent to your Waxell workspace. The signal below
# triggers it; every run executes with a hard budget, policy checks in the
# execution path, and a full trace you can open in the app.
# Field reference: https://waxell.ai/docs/runtime/waxell-yaml-reference
version: 1
defaults:
framework: claude_agent_sdk
owner: you@yourcompany.com
agents:
- name: triage
version: 1.0.0 # bump on every re-push
display_name: Triage
description: Answers a prompt and returns a concise, well-structured reply.
model: anthropic:claude-sonnet-4-6
# Claude Code built-in tools — list only what the agent needs.
tools: [Read, Glob, Grep, WebFetch]
system_prompt: |
You are a careful assistant. Answer the prompt directly, lead with the
conclusion, and keep it under 300 words unless asked otherwise.
signals:
- name: run
source_type: webhook
description: Run the agent on a prompt.
schema:
prompt:
type: string
description: What you want the agent to do
# The budget guard — the reason this runs in a runtime, not on a VM.
# When a run (or anything it spawns) would exceed this, the runtime stops
# dispatching mid-run and keeps the trace of what it was doing.
max_turns: 12
max_budget_usd: 2.0
What each part does:
| Field | Meaning |
|---|---|
framework: claude_agent_sdk | The agent runs on the Claude Agent SDK inside an isolated container. See Framework support. |
model: anthropic:claude-sonnet-4-6 | The model the run is pinned to. |
tools: [Read, Glob, Grep, WebFetch] | Claude Code built-in tools the agent may use. Every call passes through policy checks first. |
signals: - name: run | The agent runs whenever the run signal fires. schema documents the input: a prompt string. |
max_turns: 12 | The run stops after 12 agent turns. |
max_budget_usd: 2.0 | The run stops when it has spent $2.00. |
Set defaults.owner to your email. wax init reminds you if you leave the
placeholder. If waxell.yaml already exists, wax init leaves it alone unless
you pass --force. Use --dir <path> to scaffold somewhere other than the
current directory.
3. Deploy
wax push
wax push finds waxell.yaml in the current directory (or any parent) and
publishes the agent to your workspace. Run wax push --dry-run first if you
want to see what would be uploaded. To ship a change later, bump version: and
push again.
4. Run it
Fire the run signal and wait for the result:
wax signals fire run --payload '{"prompt": "Give me three risks of shipping on a Friday."}' --wait
Or watch each step as it happens, with LLM calls, tool calls and progress messages:
wax signals fire run --payload '{"prompt": "Give me three risks of shipping on a Friday."}' --stream
The response shows status: matched, the run_id, and the agent that picked
the signal up. --wait polls until the run finishes and prints the result.
--stream prints events as they land, then the result. Both stop waiting
after --timeout seconds (default 120).
The same call over HTTP, from your own backend:
curl -sS -X POST https://api.waxell.dev/api/v1/signals/run/ \
-H "X-Wax-Key: $WAXELL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "Give me three risks of shipping on a Friday."}'
See Signal HTTP Reference for following the run over HTTP.
5. Inspect the run
wax runs list # recent runs, newest first; note the Run ID
wax runs show <run_id> # summary, LLM calls, inputs, result
wax runs show <run_id> --spans # plus the full span tree
wax runs list takes --agent <name>, --status <state>, --hours <n> and
--limit <n>. wax runs show also accepts the run's trace id or workflow id.
6. Find it in the app
Open Agents in the app and select your agent (/runtime/agents/<name>). From there:
- Run: fire one of the agent's signals with a payload and watch the run come back live, with its timeline, cost, tokens and full trace.
- Telemetry: recent runs, latency, error rate, cost and token usage, with links into each run's trace.
- Bindings: the tools, domains, workflows and memory slots the agent binds.
- Versions: every version you've pushed.
Next steps
- waxell.yaml reference: every manifest field
- Register a Domain: let the agent call your own APIs
- Build & Push a Custom Tool: add a capability of your own
- Ship a Claude Agent: run the agent as a specific end user, with per-user secrets
- Operating Agents: schedules, live tail, replay and alerts