Traces
TeamsDiscoverBlogDocsHelp
Sign in
All posts

Designing Onboarding for Agents

Sep 15, 2026

For most of software history, "the user" was a person, and we shipped landing pages, signup forms, and getting started guides with that end-user in mind. Developer tools added a CLI and an API, but it was still a person reading the docs, typing the commands, and deciding what to do next.

Over the last month at Traces we've shipped a lot of work that, on its face, looks like ordinary product plumbing: an onboarding flow, an OAuth server, a few CLI commands, and some documentation.

These were intentional decisions that built towards one of our central hypothesis: people and agents will onboard to Traces, and we must design for that.

Here's what designing for agentic users looks like in practice.

Onboarding is a skill file, not a wizard

Our getting-started guide is a Markdown file at traces.com/start.md. It has YAML front matter, a name (traces-get-started), and a description. It is a skill: a document written to be read by an agent, not a human.

The end of our install script and the output of traces --help both point at it. The intended flow is that a developer says something like "set up Traces for my team" to whatever agent they already have open, the agent fetches start.md, and the agent does the work.

The file reads nothing like a tutorial. It opens with a routing step:

Classify the request before setup:

  • Individual: Set up the user's personal Traces workspace.
  • Named team: Use the supplied team name.
  • Unnamed team: Ask what the team should be called, then wait for the answer before setup work.

Then it walks through the common spine: confirm the agent can identify its own current session, check whether traces is installed, run traces whoami, run traces login if needed, list namespaces. The team route creates or reuses an organization, privately shares the current onboarding session itself into it, resolves the org's default invite, and hands back a copyable invite message. If the agent notices it has a Slack or Teams MCP available, the skill tells it to offer to send the invite for you, and to ask before sending.

There is a recovery section. There are rules like "Report only completed work in the closeout" and "If the exact current-session trace cannot be identified, stop before sharing." Those aren't there for a human reader. They're there because an agent following instructions will happily do the wrong thing confidently unless you tell it where to stop.

Writing onboarding this way forced us to add CLI primitives that a person would never have asked for. traces whoami now prints the profile URL. traces org invite <slug> list --json exists because an agent needs to find the pending unlimited invite without scraping a settings page. traces setup agents replaced the old traces setup skills because the old name hid the fact that it also installed hooks, and an agent asking for consent needs to describe accurately what it's about to do.

Every one of those changes made the CLI better for humans too, but a human wasn't the primary user for these design choices.

The agent needs its own credentials

If an agent is going to read your traces mid-session it needs access. The old answer was "generate an API key and paste it into a config file." That's a human workflow that happens to be executed by a human on behalf of an agent, and it has all the usual problems: long-lived, over-scoped, sitting in a dotfile.

So we built a remote MCP server at mcp.traces.com with a real OAuth authorization server behind it. The agent connects over Streamable HTTP, your browser opens once, you pick which Traces workspace the agent may read, and you approve traces:read. The resulting credential is bound to exactly one namespace, is revocable, and never touches an API key.

This was a substantial piece of work: a credential engine, the standards-facing HTTP layer for discovery, registration, token exchange, refresh, and revocation. None of it is visible to a person using the web app. All of it exists because an agent is now first class.

Model context is a budget, spend it carefully

Once agents were reading traces through MCP, we noticed something we'd never optimized for: our API responses were verbose in ways that cost tokens without adding information.

A trace read returned each message's text twice, once as textContent and once as an equivalent text part. Error parts almost always exactly mirrored their parent system message (707 of 709 error parts with text, in a year of data), so an agent saw every failure twice. Author records repeated display name, slug, and ID on every single trace.

For a web UI, none of that matters; the browser throws away what it doesn't render. For an agent, every duplicated byte is context window the model can't spend on reasoning. So we deduplicated text events, collapsed mirrored errors, normalized authors into a single referenced record, and changed trace listing to order by source session start rather than server updatedAt, because re-ingestion bumping timestamps was making old sessions appear "recent" to a model that has no other way to know.

This is a different discipline from API design for humans. The question isn't "is the response complete and correct." Thee question is "what is the smallest correct thing the model needs to see."

What changes when you design this way

A few things we've learned:

Consent moves into the product. When a person clicks a button, they consented. When an agent runs a command, someone has to have told it that it may. Our onboarding skill is explicit: set up hooks only when the user chooses; confirm before sending an invite; don't disclose inaccessible workspace details. The product has to carry those rules because the agent won't infer them.

Stop conditions matter more than happy paths. Human docs optimize for the case where everything works. Agent instructions need to be equally precise about where to halt. "Stop if you cannot identify the current session" is the most important line in start.md.

Structured output stops being optional. --json flags, stable URLs in command output, machine-checkable invariants. An agent can parse prose, but every time it does, you've introduced a failure mode you didn't need.

Credentials get scoped down. A person tolerates a broad API key because they're accountable for it. An agent should get exactly the access the task needs, for exactly as long as it needs it, tied to exactly one workspace.

The human is still there. This isn't about removing people. The developer is still the one who wanted their team on Traces, still the one who approves the OAuth consent, still the one who decides whether the invite goes to #eng. They're just not the one typing curl. Designing for the agent as user means designing for the human as principal, and the one whose trust has to be earned at every step where the agent acts.

Try It

Open whatever coding agent you use and say:

Read https://traces.com/start.md and set up Traces for me.

It'll figure out the rest.