Skip to main content

Quickstart: Observe Your Agents

Add observability to any Python AI agent in under 5 minutes. There are three levels of instrumentation -- most agents only need the first one:

  1. Auto-instrument -- 2 lines of code, zero changes to your agent.
  2. Decorators -- when you want more structure, or something auto-instrumentation can't see.
  3. WaxellContext -- explicit lifecycle control when decorators don't fit your code shape.

Before You Start: Two Shortcuts​

Claude Skills -- don't instrument by hand at all. Install the Waxell skills and your coding agent instruments and governs your agents for you. If you use a coding agent, start here.

Working examples -- complete, runnable agents for every provider, framework, and pattern: instrumentation, decorators, policies, multi-agent, RAG, streaming, per-end-user attribution. Clone one that matches your stack instead of starting from scratch.

Two fast paths to your first run​

Pick the one closest to what you have today. All three end with a fully-instrumented agent emitting runs to your tenant — they just start from different places.

If you...UseTime
Want a working agent to copy and adaptAgent Examples Repo — 10 conversational REPLs, each demonstrates one Waxell capability (decorator, tools, RAG, end-user attribution, policies, multi-agent, streaming, …)~3 min
Already have a Python agent and want to add Waxell to itThe instrument-with-waxell-observe Claude Code skill — open your agent in Claude Code, invoke the skill, it installs wax + the SDK, wires the decorator, and verifies one run lands~5 min
Want to understand the pattern by hand firstSkip to Prerequisites below — the manual walkthrough covers the same flow Path A and Path B automate~10 min

Path A — Clone a working example​

The waxell-ai/waxell-agent-examples repo ships 10 self-contained conversational agents covering every Waxell capability. Each example is one folder with agent.py, setup.sh, README.md, and a requirements.txt — no cross-dependencies.

git clone https://github.com/waxell-ai/waxell-agent-examples.git
cd waxell-agent-examples

# Seed .env from your local wax profile (or copy .env.example and fill in by hand)
./scripts/seed-env-from-wax.sh

# Pick an example, install its deps, run it
./scripts/setup-example.sh 01-hello-waxell
source examples/01-hello-waxell/.venv/bin/activate
python examples/01-hello-waxell/agent.py

After a few REPL turns, wax runs list --limit 5 shows the runs in your tenant. The numbered index in the examples README tells you which example demonstrates which capability — copy whichever is closest to what you're building, rename the agent, and start changing the system prompt.

Path B — Instrument your existing agent​

If you have a Python agent you already use, the instrument-with-waxell-observe Claude Code skill retrofits it without you copy-pasting from anywhere. Open your agent in Claude Code and invoke:

/instrument-with-waxell-observe

The skill walks the file, then:

  1. Checks wax CLI is installed; installs and configures it if not.
  2. Adds the two-line decorator pattern (waxell.init() at module top + @waxell.observe(...) on your entry function) at the right place in your file.
  3. Installs waxell-observe and pins a known-working version.
  4. Runs your agent once to verify a run lands in your tenant.
  5. Walks you through one starter governance policy (PII block, cost cap, etc.) if you want it.

Your existing agent runs unchanged afterward — it just also emits full telemetry. The skill source + README is in waxell-ai/claude-skills.

Path C — Manual walkthrough​

If you'd rather understand the pattern by hand, the rest of this page walks through the exact same flow Path A and Path B automate. Continue with Prerequisites below.


Prerequisites​

  • Python 3.10+
  • A Waxell API key (get one from your Waxell control plane dashboard)

Install the Observe SDK, plus the waxell package for the wax CLI — used below to confirm your runs landed:

pip install waxell-observe   # the instrumentation SDK
pip install waxell # the wax CLI (verify runs, manage your tenant)

Verify your install​

wax --version                     # CLI is installed and on your PATH
python -c "import waxell_observe" # SDK imports cleanly (no output = success)

Once your API key is set (via the env vars shown below, or wax login), wax whoami confirms the credentials resolve and wax doctor runs a full health check. If wax isn't found or the import errors, see the CLI install troubleshooting (command not found, PATH, PEP 668).

Level 1: Auto-Instrument (2 lines)​

Call init() before importing any LLM SDK. This auto-instruments 200+ libraries (OpenAI, Anthropic, Groq, LiteLLM, Cohere, Mistral, Gemini, LangChain, LlamaIndex, vector DBs, and more) with zero changes to your agent code.

import waxell_observe as waxell

waxell.init(api_key="wax_sk_...", api_url="https://acme.waxell.dev")

# Import LLM SDKs AFTER init()
from openai import OpenAI

client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello!"}]
)
# Automatically traced: model, tokens, cost, latency

That's it. Every LLM call in your process is now tracked -- model, tokens, cost, latency, prompt/response previews -- and visible in the Waxell dashboard.

Environment Variables

You can also configure via environment variables:

export WAXELL_API_URL="https://acme.waxell.dev"
export WAXELL_API_KEY="wax_sk_..."

Then just call waxell.init() without arguments.

See Auto-Instrumentation for the full library list and configuration options.

Level 2: Decorators (more detail, or things auto-instrumentation missed)​

Auto-instrumentation sees your LLM and framework calls. It doesn't know which function is your agent, what your tools do, or why your agent made a decision. When you need that structure, add decorators.

Start with @observe on your agent's entrypoint -- it creates a named, tracked run for each call with input/output capture and policy enforcement:

import waxell_observe as waxell

waxell.init()

from openai import OpenAI

client = OpenAI()

@waxell.observe(agent_name="support-bot")
async def handle_ticket(query: str) -> str:
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": query}],
)
return response.choices[0].message.content

Then decorate the internal functions you care about. Each decorated call becomes a structured span in the trace:

@waxell.tool(tool_type="vector_db")          # tool calls: name, inputs, output, duration
def search_knowledge_base(query: str) -> list[dict]: ...

@waxell.retrieval(source="pinecone") # RAG: query, documents, scores
async def retrieve_docs(query: str) -> list[dict]: ...

@waxell.decision(name="route_query", options=["faq", "technical", "billing"])
async def classify_query(query: str) -> dict: ... # routing: chosen option, reasoning

There are also decorators for reasoning steps (@reasoning_dec), pipeline steps (@step_dec), and retry logic (@retry_dec), plus inline one-liners -- waxell.score(), waxell.tag(), waxell.metadata(), waxell.step() -- for enrichment without wrapping anything. Session and user attribution go straight on the decorator:

@waxell.observe(agent_name="chat-agent", session_id="session-abc123", user_id="user-456")
async def handle_message(message: str) -> str: ...
Behavior outside @observe

Behavior decorators are no-ops outside an @observe or WaxellContext scope -- your functions work normally with zero overhead.

See Decorator Pattern for the full @observe reference and Behavior Tracking for every decorator and inline function.

Level 3: WaxellContext (full control)​

If decorators don't fit -- you can't wrap the entrypoint, you're instrumenting someone else's framework loop, or you need explicit control over when a run starts and ends -- use the context manager:

from waxell_observe import WaxellContext

async with WaxellContext(
agent_name="chat-agent",
session_id="session-abc123", # groups related runs
user_id="user-456", # per-user cost attribution
) as ctx:
response = await call_llm(prompt)
ctx.set_result({"output": response})

Everything that works inside @observe -- auto-instrumented LLM calls, behavior decorators, inline enrichment -- works identically inside a WaxellContext block.

See Context Manager for the full reference.

What You Get in the Dashboard​

Every run appears in the Waxell dashboard with:

  • Agent name, workflow, and execution status
  • Captured inputs and outputs
  • LLM calls with model, tokens, cost, latency, prompt/response previews
  • Behavior spans -- tool calls, retrievals, decisions, reasoning steps
  • Scores, tags, and metadata
  • Session timeline grouping related runs, with per-user cost attribution

Next Steps​