Agent config
The read a running deployment makes on every call. Its payload, its refusals, and the three settings that connect a deployment to it.
GET /agent-config/{routingKey}Your deployment makes this read on every call an agent takes, between the webhook arriving and the agent answering. It fetches the agent's settings and its stored prompt files, uncached, so an edit made through the agents API is live on the next call.
You do not call it yourself. It is documented here so that the path your prompts take to a call is visible, and so a deployment's logs can be read without guesswork.
Authentication
The deployment sends its own key, the
deployment key, as a bearer token. The routing
key in the URL identifies the agent; the API key authenticates the caller and
confines the answer to its organization and to the cores its
permissions.cores reaches. The manage-agents permission is not needed here,
and the deployment key does not have it.
A key issued in the console reaches every agent in its organization, so one
deployment key serves all of them and a new agent needs nothing added to it.
Whether a key may read agents is a single setting rather than a list, so a key
that has it turned off is refused for every agent, not for some. That is the
403 below, and it is a key that changed rather than an agent that is missing
something.
The payload
{
"version": 1,
"agent": {
"slug": "clinic-one",
"name": "Clinic One",
"instructionSource": "database",
"timezone": "America/New_York",
"phoneNumber": "+15035550142",
"transferNumber": "+15035550188",
"variables": { "clinicName": "Clinic One" }
},
"instructions": {
"main": [
{
"path": "instructions.md",
"content": "…",
"versionId": "sha256-860e7daee313",
"updatedAt": "2026-09-16T18:00:21.418Z"
}
]
}
}| Field | Description |
|---|---|
version | The dialect of this payload, currently 1. A consumer that does not recognise the version must refuse rather than guess |
agent | The agent's settings: the Agent object without routingKey, tenantPath and kind. The caller already holds the routing key it asked on, and the other two answer questions about managing an agent rather than serving a call. variables is here, since prompts are compiled from it |
instructions | A map from directory to the stored File objects, content included. Empty for a repo agent |
agent.variables is that agent's own
prompt variables, which the
deployment exposes to its prompts as tenant. followed by each name. It is
always an object and {} for an agent with none, so a deployment never has to
tell "no variables" from "this payload does not carry them". Reading it needs
kit 0.21.1 or later, and an older deployment simply never looks at the field.
versionId is byte-identical to the id the deployment computes for the same
file on disk, so a stored file and a repo file can share one provenance record.
updatedAt is ISO 8601 UTC with milliseconds and a Z, the same form the
File object carries on the
instruction routes.
What it answers
| Case | Answer |
|---|---|
An agent on repo | 200 with "instructions": {}, from one indexed lookup. The deployment's own files answer the call |
An agent on database with files stored | 200 with every stored file, read in one statement, so an answer cannot straddle an edit |
An agent on database with no file stored | 409 NO_INSTRUCTIONS, never an empty 200 |
| A routing key that does not exist, is malformed, or belongs to another organization | A bare 404 NOT_FOUND |
A key whose permissions.cores does not reach the agent | 403 FORBIDDEN |
| A failed query | 500 DATABASE_ERROR |
Every refusal is deliberately unambiguous. An agent that reads its prompts from
the database and cannot get them has to fail the call, so that the number's own
failover takes over. Nothing here answers with a shape a deployment could read
as "carry on with defaults". A missing agent is a bare 404, a database
agent with nothing stored is a 409, and a failed read is a 500. The 500
is kept apart from the 404 because a missing agent is permanent and a failed
read is not.
No rate limit, no writes
The read is not rate limited, for the same reason telemetry ingestion is not:
it sits on a deployment's call path, and a 429 here would fail a live call.
It writes nothing, not even the key's last-used timestamp, because it runs
inside a voice-latency budget. Every answer is Cache-Control: no-store.
The alias under /api
The same route also answers on
GET /api/agent-config/{routingKey}That is the path a deployment on kit 0.18.0 builds from its
SUBCORE_CONSOLE_URL setting, so a deployment moves its config read to
api.subcore.ai by changing that one setting, without a kit release. The alias
stays until a kit release reads this service directly.
Connecting your deployment
Three settings in the deployment's environment tie it to this API. The rest of the deployment's configuration is documented with the deployment itself.
| Setting | Value | What it does |
|---|---|---|
SUBCORE_API_KEY | The deployment key | Authenticates the config read and the telemetry the deployment ships |
SUBCORE_CONSOLE_URL | https://api.subcore.ai | Where the config read goes |
TELEMETRY_PROFILE | structural | Events leave the deployment without conversation content |
SUBCORE_API_KEY=sk_live_...
SUBCORE_CONSOLE_URL=https://api.subcore.ai
TELEMETRY_PROFILE=structuralThe deployment key is not the key that manages agents. It is issued from the deployment's own page in the Subcore console, not from an agent's. It reads configuration and sends telemetry. It cannot manage agents, and it never has the manage-agents permission.