Setup
Everything on this page is shared by all three tracks. Do it once. By the end you’ll have an agent identity, three secrets in a.env file, a
short script that proves those credentials talk to the platform, and the one
call that turns the identity into an agent Swarmd will actually route to.
Already have
SWARMD_AGENT_ID and SWARMD_CLIENT_SECRET from someone on your
team? Skip to Step 4.Step 1: Get a tenant
A tenant is your organisation on Swarmd. Everything — agents, users, policies, subscriptions — lives inside one. If your organisation is already on Swarmd, ask an admin to add you. Otherwise create one:Step 2: Create your agent identity
Registration takes two calls, and the one that hands you credentials comes first.POST /registry/v1/agents creates an identity: a name, an OAuth2
service account, and a webhook signing key. It asks for no URLs, because your
agent doesn’t exist yet.
Credentials first, code second. This is deliberate: you get working
credentials before you have anything to point Swarmd at, so you can build,
run and test the agent locally with real identity.What you hold after this call is an unbootstrapped shell — an identity with
no A2A agent card behind it. It can mint
tokens, but it cannot be subscribed to anything, cannot send or receive relay
traffic, and cannot be sent a webhook. The registry reports its status as
BOOTSTRAP_REQUIRED and refuses to use it: “Agent must be bootstrapped
before it can be used.”You clear that in Step 7, once there’s a
real agent serving a real card.Step 3: Save the three secrets
The response contains three values:What happens if I skip the webhook secret?
What happens if I skip the webhook secret?
Your agent still works. Outbound calls are unaffected — they only use
clientSecret.What you lose is push. When an operator subscribes your agent to a new
sub-agent or grants it a new MCP server, Swarmd normally POSTs a signed kick to
your agent’s /admin/webhook and the agent re-discovers its catalogue in place.
Without the secret, that endpoint refuses every delivery with 503, and
somebody has to POST /admin/refresh (or restart the pod) by hand after each
change.Set it. It costs one line of .env.Step 4: Install the SDK
Install the package for your track. The wrappers pull inswarmd-sdk plus
their framework, so you only install one thing.
a2a-sdk, mcp, and their framework to
tested ranges, and those ranges have real teeth — see
dependency ranges.
Step 5: Write your .env
The SDK reads configuration from environment variables and loads a .env file
automatically via python-dotenv.
.env
Why do I need to set BASE_URL and TOKEN_URL if they're the defaults?
Why do I need to set BASE_URL and TOKEN_URL if they're the defaults?
For
swarmd-sdk on its own, you don’t — SwarmDClient.from_env() falls back
to the production URLs.For the wrappers you do. Their create_runtime() only configures the
runtime when all four of SWARMD_AGENT_ID, SWARMD_CLIENT_SECRET,
SWARMD_BASE_URL and SWARMD_TOKEN_URL are present. Leave any one unset and
you get standalone mode: the agent boots and serves, but discovers no
sub-agents and no MCP tools.That’s a deliberate escape hatch for local development without a Swarmd
account — but it’s also the single most common “why can’t my agent see
anything?” cause. If discovery is silently empty, check all four.Step 6: Confirm it works
Before writing any agent code, prove the credentials are good:check.py
get_agent_subscriptions() takes your own agent id as an argument even though
the client already authenticates as that agent — the endpoint is shared with
tenant-admin callers who can query any agent. When an agent calls it, the
registry compares the id against the JWT subject and rejects a mismatch with
403, so passing anything other than your own id will fail.Authenticated as … / Subscribed to 0 agent(s)
Authenticated as … / Subscribed to 0 agent(s)
Correct. An unbootstrapped shell has no subscriptions and can’t be given
any until its card is attached, and even a bootstrapped agent starts with none
until an operator grants them. Your credentials work — that’s what this step
was checking. Move on.
ValueError: Missing required environment variables
ValueError: Missing required environment variables
.env isn’t being found or isn’t being read. Confirm the file sits in the
directory you run python from, and that the variable names match exactly
(SWARMD_AGENT_ID, not SWARMD_AGENTID).AuthenticationError / TokenRefreshError
AuthenticationError / TokenRefreshError
The token endpoint rejected your client credentials. Usually one of:
SWARMD_CLIENT_SECRETwas truncated on copy — it has no separators, so a partial paste looks plausible.- The secret was rotated with
POST /registry/v1/agents/{agentId}/credentialand.envstill holds the old one. - The agent was deregistered, which revokes its service account.
SWARMD_TOKEN_URLpoints at the wrong realm or the wrong environment.
Step 7: Attach your agent card
This is the second half of registration, and the one that makes the agent real. Come back to it once your agent is running and serving its card — the SDK serves it at/.well-known/agent-card.json — on a URL Swarmd can reach.
You can build, run and iterate on the agent before this call; nothing that
involves another party — subscriptions, relay traffic, webhooks — works until
after it.
With the card attached, the shell becomes a routable agent: operators can
subscribe it to sub-agents and grant it MCP servers, the relay will carry its
traffic, and the webhook kicks described in
Core concepts start
arriving.
Every
PUT appends a version. It is a full replacement, not a patch —
send the complete body each time. Swarmd re-resolves the card, appends a new
immutable version, and leaves the previous one intact;
GET /registry/v1/agents/{agentId}/versions returns the history. Bump
registryVersion on each publish.To change just the tenant-facing name or description, use
PATCH /registry/v1/agents/{agentId} instead — that edits identity metadata
and doesn’t touch the card.Next
Core concepts
What the runtime, the two token audiences, and the refresh loop actually
do. Ten minutes that make every helper obvious.
Skip to building
Straight into code: Core SDK,
Google ADK, or
LangChain.
