Skip to content

First agent in 15 minutes

This is the recommended path from "I have an LLM app" to "NullRun is gating my spend and tools". Skip the deep dives — link to them when you actually need them.

1. Sign up and create an API key (2 min)

  1. Go to nullrun.io and sign in.
  2. Open API keysCreate key.
  3. Pick a name (e.g. "my-first-agent") and the workflow you want the key bound to. Each key is workflow-scoped since Phase 139 — it represents one agent run, not one workspace.
  4. Copy the key (nr_live_…) shown once and store it somewhere safe (env var, secret manager). You'll need it in step 3.

2. Install the SDK (1 min)

shell
pip install "nullrun[openai]"     # raw openai SDK + tracking
pip install "nullrun[langgraph]"  # if you're using LangGraph
pip install "nullrun[agents]"     # if you're using OpenAI Agents SDK
pip install "nullrun[all]"        # every vendor extra — heaviest install

See Install for the full list of extras. For this walk-through nullrun[openai] is enough.

3. Wire NullRun into your code (5 min)

Pick the pattern that matches what you have today:

A. You already call client.chat.completions.create(...)

my_agent.py
import nullrun
from openai import OpenAI
from nullrun import init_or_die, protect, shutdown

# 1. One line — reads NULLRUN_API_KEY from env if not passed.
init_or_die(api_key="nr_live_...")

client = OpenAI()

# 2. @protect gates every call through NullRun before it runs.
@protect
def answer(prompt: str) -> str:
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}],
    )
    return response.choices[0].message.content


# 3. shutdown() flushes pending events and closes the WS cleanly
#    — register via atexit in production scripts.
if __name__ == "__main__":
    try:
        print(answer("What does NullRun do?"))
    finally:
        shutdown()

That's the whole integration. Every call inside answer() is now cost-attributed. There is no SDK call you have to remember to make for tracking — auto-instrumentation picks up the OpenAI HTTP call automatically. @protect is the gate (budget pre-flight + kill check + sensitive-tool decision), not the tracking mechanism.

B. You use a framework (LangGraph / CrewAI / OpenAI Agents / AutoGen / LlamaIndex)

Auto-instrumentation does the same thing — see Use with LangGraph or any of the other framework how-tos. Most of the time the only line you add is the init() call.

4. Set a budget (1 min)

In the dashboard, open the workflow your key is bound to and set a budget_cents. A reasonable starter budget:

Use case Suggestion
Personal / dev experiment 500 ($5) per period
Single-tenant internal tool 2000 ($20) per period
Customer-facing AI feature 10000 ($100) per period with alerts

Periods are either calendar-month UTC (Lite) or your billing cycle (paid plans via Polar). See Budgets → Period rollover for the detail.

5. Run and observe (2 min)

shell
python my_agent.py

Then open the dashboard → Workflows → your workflow → Decisions. You'll see every /gate call (one per @protect-wrapped invocation), the policy verdict (allow / block / rate_limit), and the cost.

For real-time spend, hit GET /api/v1/orgs/{org_id}/status — it returns current_spend_cents, budget_cents, time_to_exhaustion, and your plan caps in a single call (see the Single-call status example under "Common request patterns").

6. Tighten or loosen (remaining time)

Common next steps, in rough order of how often they're needed:

  1. Block a tool the agent shouldn't touch — see Tool policies and the recommended ToolBlock starter list in the Tool catalog.
  2. Allow over-budget for long agents — see Chain context → soft mode.
  3. Forward every error to Sentry — see Error handling → on_error hook.
  4. Pre-flight keys before risky calls — see Human approval.

What this walk-through didn't cover