Users

Use the Users resource when your product has end-users and each user needs isolated data.

The key is user_id. Pass it on agents, runs, tasks, memories, and permissions. Without it, resources are account-level; with it, each end-user gets isolated agents, run history, memory, and permission policies.

Start with user_id

The same user_id on every call keeps one customer's world separate:

The TypeScript SDK wraps all of these: client.agents, client.runs, client.tasks, client.users, client.memories, and client.permissions.

List endpoints take the same filter, so you only fetch one tenant:

Python

Usage and billing

Isolation is about data. For billing, any run carrying a user_id settles on your prepaid balance (the API meter), not on your platform plan. See Billing & Usage. You can still see and cap each end-user individually: GET /api/v2/usage/end-users rolls up each end-user's completed runs, cost, and tokens for the current billing period:

Python

Cap every end-user account-wide, or throttle one specific end-user with a per-profile override:

Cap semantics, error codes, and per-day cost series
  • Per-profile overrides win over the account-wide defaults. run_limit=0 blocks an end-user entirely; None clears an override back to the account default.
  • A capped end-user's next run returns 402 with END_USER_RUN_LIMIT_REACHED or END_USER_COST_LIMIT_REACHED; rate bursts return 429 END_USER_RATE_LIMITED. Other end-users (and your own runs) are unaffected.
  • The rollup endpoint reports the same counters and the EFFECTIVE caps per row, so the numbers always reconcile.
  • For cost attribution over time, client.billing.usage_timeseries(user_id="cust_123") returns that end-user's daily token + USD buckets.

User profiles

Profiles are auto-created the first time you use a new user_id; manage them directly when you want names and emails attached:

Python

Strict multi-tenant mode

The classic multi-tenancy bug is forgetting user_id on one call: the data silently lands in the account-level scope, invisible to your end-users. Strict mode rejects those requests instead, and it is on by default for new API accounts:

Python

Building for just yourself? Turn it off and drop user_id everywhere:

Python
Where strict mode is enforced, and older accounts

Enforced wherever a request scopes data: agent, task, run, skill, and custom-MCP-server creation (a run inheriting scope from its scoped agent passes without an explicit user_id), plus every memory operation. App connections and replies to pre-existing unscoped runs are exempt.

Accounts created before mid-2026 (and platform-product accounts) default to off; opt in with client.settings.update(require_end_user_id=True).

Best practices

  1. Use your own stable internal ID as user_id, and pass it on every relevant request
  2. Do not mix scoped and unscoped writes for the same product flow
  3. Keep permission policies and memories aligned to the same user_id
  4. Keep strict mode on so a forgotten user_id fails loudly instead of writing to the account scope

Next: Runs · Human-in-the-Loop · API Reference

Was this page helpful?