How to organise your API keys so the Activity Feed tells you something

Step-by-step guide for NOAN users: split one shared API key into per-category agent keys so the Activity Feed reads by category. Covers naming, scopes, migration and verification. Blog-post source.

Published:
Updated:
How to organise your API keys so the Activity Feed tells you something

How to organise your API keys so the Activity Feed tells you something

The Activity Feed shows every action in your workspace — by your team, and by every API key. That means the name you give a key is what everyone reads. Get it right and the feed answers "what did our agents do this week?" at a glance. Get it wrong and everything reads as one anonymous actor.

Most workspaces start with one key doing everything, because that is the fastest way to get an agent running. This guide is the tidy-up: eight steps, about an hour.


Step 1 — Decide your categories

Group your agents by the kind of work they do, not by which agent they are. Five or six categories is right for most teams. Ours are:

Demand (marketing, social) · Deal (sales, outbound) · Customer (onboarding, support) · Facts (reporting, research) · Ops (internal admin) · General (a catch-all agent that handles anything unrouted)

Name yours after your own work. The test: could a teammate scanning the feed tell what kind of work happened without opening anything?

One key per category, not per agent. Per-agent keys become unmanageable past a dozen agents, and the feed already shows the task or fact title for the detail. Split a category further only where there is a real privilege boundary — for example, an agent whose output is public and must never read customer data.

Step 2 — Choose a naming convention

Whatever you pick, apply it everywhere. Ours:

<Agent family> - <Category>      e.g.  Verity - Demand
Claude - <First name>            for a person's own key
<App name> - <Instance>          for an app or website

Two rules that matter more than the exact format:

  • A category is one word, from your fixed list. No free text.
  • Never put a person's name on a fleet key. That is how you end up with "Sarah's key" running six agents long after Sarah moved teams.

Step 3 — Create the keys

In Account → Settings → API, create one key per category.

  • Mint them under a dedicated agent account if you have one. Failing that, pick one human account and use it for every fleet key, so attribution stays consistent.
  • Set the attachment type — website, app, or agent. The feed filters on this independently of the name, so it is what lets you isolate "just the agents".
  • Copy each value once. Keys are shown at creation and cannot be retrieved later.

Step 4 — Give each key only the access it needs

Each key gets an explicit set of scopes: fact:read, contact:write, task:read, and so on. A route the key lacks returns 403 — and that is permanent, not a glitch to retry.

Start from what each category actually does:

CategoryTypical scopes
Demandfacts read, tasks read/write. No contact access — its output is public
Dealcontacts read/write, tasks read/write, facts read
Customercontacts read/write, tasks read/write, facts read
Factsfacts read/write — usually the only category that writes facts
Opstasks read/write, facts read, contacts read only
Generalbroad, because by definition it handles anything

Two things worth being strict about:

  • Only one category should write facts. Facts are your source of truth; the fewer things that can change them, the better.
  • Seed and setup scripts write facts once, at install. Run those under a human key so your day-to-day agent keys never need write access at all.

Step 5 — Store the keys where your agents run

Put each key in your secret store — GitHub Actions secrets, your host's environment variables, whatever you use. Name the variables to match the keys, with one prefix so they sort together:

NOAN_KEY_DEMAND   NOAN_KEY_DEAL   NOAN_KEY_CUSTOMER
NOAN_KEY_FACTS    NOAN_KEY_OPS    NOAN_KEY_GENERAL

Step 6 — Point each agent at its key

Set the key in the agent's environment, one category at a time. Migrate the smallest, least frequent category first, confirm it in the feed, then continue.

If several agents share one job or process, set the key per step rather than for the whole job — otherwise they all report as whichever category you picked for the default.

Keep your original shared key in place while you migrate. It doubles as a progress meter: anything still showing the old name in the feed has not moved yet.

Step 7 — Verify in the feed, not in the logs

A green run does not prove anything here. If a key is missing, most setups fall back to whatever else is available and the run succeeds under the wrong identity.

Check two things instead:

  1. The feed shows the new key name for that agent's writes.
  2. "Last used" on the keys page moves for agents that only read.

Once every category is confirmed, remove the shared key from your agents' environments.

Step 8 — Give every person their own key

Anyone using an API key personally — a coding assistant, a script, an integration they are testing — gets their own, named for them, minted under their own account and kept local.

This is the step that makes the feed honest. Without it, one person's key carries several people's work and the feed cannot tell you who did what.


Optional: lock down your public-facing agents

If an agent's output is public — social posts, website copy, outbound email — it is reading untrusted input from the internet. You can limit its key to specific stacks, so it can only reach the knowledge it genuinely needs.

One thing to plan for: a stack limit applies to reading and writing. So everything that agent reads has to live inside the stacks you allow it — including its own configuration. Work out its full list before you apply the limit.


What you end up with

A feed you can filter by category, keys you can rotate one at a time without touching anything else, and a public-facing agent that cannot reach your customer list even if something goes wrong. Most of the value shows up the first time someone asks "what has the sales agent been doing?" and the answer takes five seconds.