Runtime limits
Set the sizes, counts, and deadlines the Runtime holds a Tenant to.
import { createAdmin } from "@nylorun/admin";
const admin = createAdmin();
const { limits } = await admin.settings.limits.get();
console.log(limits.httpToolTimeoutMs); // 300000
await admin.settings.limits.put({
limits: { httpToolTimeoutMs: 600_000, sessionQueuedMessages: 20 },
});From a terminal:
npx nylorun tenant settings limits get
npx nylorun tenant settings limits put limits.jsonHow large, how many, and how long what crosses the Runtime may be is the
Tenant's Runtime limits. They are a Tenant setting, set with a management key
the same way on a local or a remote Tenant: admin.settings.limits,
nylorun tenant settings limits, or GET / PUT /v1/tenant/limits. In
Studio, the Tenant page's Limits tab lists
them by area beside their defaults and edits one at a time.
Set limits
A put replaces them all. A limit left out takes its default. get
returns every limit in force ({ limits }), with the default filled in for each
the Tenant has not set, so putting back what get printed fixes today's
defaults as the Tenant's own values. Keep the limits you change in one place,
such as a limits.json in your repository holding only those, and put the
whole set each time.
- A limit above its ceiling, or under its floor, is
400, naming the bound and why, and nothing changes. - Each limit is read where it is checked, so a new value holds for the next request, write, call, or turn.
- An agent manifest's setup commands and input files are checked when it is saved, an Agent's labels whenever they are set, and a secret's value and hosts when it is written.
- An Agent made before a limit was lowered keeps running, within the lower limit where one applies at run time, such as a setup command's timeout or a disk version.
A name ending in Bytes counts bytes, Ms milliseconds, and Chars
characters. Every value is a whole number, at least 1, except
modelProviderRetries, triggerJitterPercent, and triggerJitterMaxMs, which
may be 0.
What crossing one looks like
| Limit | Past it |
|---|---|
requestBodyBytes | 413 limit_exceeded. |
recordEntryBytes | A write into the session's record is 413 limit_exceeded (details.limit: "recordEntryBytes") to an API client, and limit_exceeded to a harness. A turn whose harness reports more fails. |
pageItems, exportPageItems | A page asked for with a larger limit holds this many, with a cursor to the rest. |
toolAnswerBytes | The tool call fails to the model with mcp.too-large or http.too-large. |
toolAttempts | The tool call fails to the model with tool.interrupted. |
sessionQueuedMessages | One more message is 429 queue_full. |
triggerRunsPerHour | Later runs that hour are skipped, rate_limited. |
webhookBodyBytes | The delivery is 413, before it is verified. |
flowMapItems, flowLoopIterations | The flow's turn fails with map.too-many-items or loop.too-many-iterations. |
folderFiles, folderBytes | The save of an agent manifest is 413 limit_exceeded, naming the limit in details.limit. |
folderTextFileBytes | The save of an agent manifest is 422 folder_invalid. |
Elsewhere, the error message names the limit, its value, and where it is set
(PUT /v1/tenant/limits).
Limits a harness gets
A harness learns these in turn.start.limits and must respect them. A
custom harness reads them there rather than assuming the
defaults.
| Limit | What it holds | Default | Ceiling |
|---|---|---|---|
recordEntryBytes | One event's payload, or one effect outcome, in a session's record. A transcript edit fills events up to it. | 960 KiB | 960 KiB: a 1 MiB record entry, less the event's envelope |
modelCallBytes | A model call's body at the Model Gate. | 32 MiB | About 512 MiB: one string |
modelFileBytes | One file the Model Gate sends a model. | 8 MiB | About 384 MiB: its base64 in one string |
toolAnswerBytes | An MCP or HTTP tool's answer the Tool Gate keeps, and the tool call bodies it reads. | 8 MiB | 32 MiB: half a Harness API frame |
harnessStateBytes | A custom harness's state per session, as JSON. | 256 KiB | 32 MiB: half a Harness API frame |
chunkBytes | One chunked Harness API answer or upload chunk, such as a range of a skill file or an artifact, and one range of a disk copy. | 16 MiB | 48 MiB less 64 KiB: its base64 in one Harness API frame |
folderEntries | The files of one folder version a harness writes, such as Nylorun's harness's outputs folder. | 10,000 | About 4.6 million: entries of a folder's listing in one string |
Limits only the Runtime checks
The names that start with environment are kept from before Agents. They
apply to an agent manifest's runtime section and to an Agent.
Requests
| Limit | What it holds | Default | Ceiling |
|---|---|---|---|
requestBodyBytes | A Runtime or Management API request's JSON body. | 1 MiB | About 512 MiB: one string |
messageParts | Parts, text and files, of one user message. | 32 | One request body |
pageItems | Items one page of a listing holds. A page with no limit holds the route's default (50), or this when lower. | 200 | About 179 million: one response body |
exportPageItems | Calls one page of the model call export holds (admin.models.exportCalls(), nylorun tenant calls). | 1,000 | One response body |
environmentEventItems | Events one read of an Agent's events returns. from reads on. | 1,000 | One response body |
inlineFileBytes | One file a message carries inline (AG-UI, A2A). Such an endpoint reads one file's base64 and requestBodyBytes more. | 20 MiB | About 384 MiB: its base64 in one string |
a2aWaitMs | How long a blocking A2A SendMessage waits before it answers WORKING. | 5 min | A timer |
errorExcerptChars | How much of a failed MCP server's or HTTP tool's answer an error quotes. | 2,000 | One record entry, escaped |
traceContentBytes | One content attribute of an exported span. | 8 KiB | 960 KiB: one record entry |
Labels
| Limit | What it holds | Default | Ceiling |
|---|---|---|---|
environmentLabels | Labels on one Agent, checked whenever they are set. | 32 | One request body |
artifactLabels | Labels on one artifact, checked when it is uploaded. | 32 | One request body |
labelKeyChars | The longest label key, an Agent's or an artifact's. | 63 | One request body |
labelValueChars | The longest label value. | 256 | One request body |
An agent manifest's runtime section
Checked when the manifest is saved.
| Limit | What it holds | Default | Ceiling |
|---|---|---|---|
environmentSetupCommands | Setup commands in one runtime section. | 16 | One request body |
environmentFiles | Input file entries in one runtime section. | 16 | One request body |
environmentFilesPerEntry | Files one input file entry by hash names. | 1,000 | One request body |
environmentSecretSlots | Secret slots one runtime section declares. | 64 | One request body |
manifestDescriptionChars | An agent manifest's description. | 1,024 | One request body |
secretDescriptionChars | A secret slot's description. | 500 | One request body |
setupCommandChars | One setup command. | 4,096 | 43,690: one argument of /bin/sh -c, at 3 UTF-8 bytes a character |
setupCommandMs | The longest timeout a setup command may ask for. A command's default is 10 minutes. | 30 min | A timer |
setupOutputChars | The end of a failed setup command's output its event keeps. | 4,096 | One record entry, escaped |
setupReasonChars | The end of that output a failed pod's reason quotes. | 500 | One record entry, escaped |
setupCommandExcerptChars | The start of the command the reason quotes. | 80 | One record entry, escaped |
Secrets
Checked when a secret is written, and a manifest's slots when it is saved.
| Limit | What it holds | Default | Ceiling |
|---|---|---|---|
secretValueChars | The value of an environment_secret or environment_variable. | 8,192 | One request body |
secretHosts | Hosts one environment_secret may be sent to (allowedHosts). | 32 | One request body |
Disk versions
| Limit | What it holds | Default | Ceiling |
|---|---|---|---|
diskVersionEntries | Entries (files, links, empty directories) in one version of an Agent's disk. | 200,000 | About 1.9 million: one disk listing in a Harness API frame |
diskVersionBytes | Bytes of files in one disk version. | 10 GiB | A number |
diskLeaseMs | How long a disk copy's lease lasts unrenewed. The copy renews it every quarter of it. | 2 min | A timer |
diskPodWaitMs | How long a disk copy waits for a pod's engine to connect. | 60 s | A number |
Model calls
See Timeouts and retries.
| Limit | What it holds | Default | Ceiling |
|---|---|---|---|
modelRequestMs | The longest one provider request may take. | 600 s | A timer |
modelIdleMs | How long a provider's stream may go without an event before the attempt is abandoned and tried again. | 300 s | A timer |
modelAttempts | Attempts per model call, the first included. | 3 | A number |
modelRetryDelayMs | The delay before the second attempt. It doubles each time, with jitter. | 2 s | A timer |
modelProviderRetries | Retries the provider's SDK makes within one attempt. | 2 | A number |
modelRetryDelayMaxMs | The longest delay the provider's SDK waits before one. | 60 s | A timer |
Tools
| Limit | What it holds | Default | Ceiling |
|---|---|---|---|
toolAttempts | Sends of an MCP or HTTP tool call, across crashes and lost hops, before it fails as tool.interrupted. | 3 | A number |
httpToolTimeoutMs | The longest timeoutMs an HTTP tool may ask for, checked when the manifest is saved and at each call. A tool's default is 60 s. | 300 s | A timer |
mcpSnapshotBytes | What a session pins of its MCP servers' tools and instructions, which every turn carries. A server past it is left out, with a diagnostic. | 4 MiB | 16 MiB: a quarter of a Harness API frame |
mcpPreviewMs | How long an MCP server preview may take. | 15 s | A timer |
mcpMetadataBytes | The protected-resource metadata document a preview reads. | 64 KiB | About 512 MiB: one string |
toolRules | Rules in the Tenant's tool policy. | 200 | One request body |
toolRuleFieldChars | A rule's tool, server, or agent selector, and a when path. | 200 | One request body |
toolRuleTextChars | A rule's reason, and a matches expression. | 500 | One request body |
modelBudgets | Model budgets the Tenant sets. | 100 | One request body |
Sessions
| Limit | What it holds | Default | Ceiling |
|---|---|---|---|
sessionQueuedMessages | Messages one session's queue holds while its turn runs or waits. | 100 | A number |
Triggers and wakes
See Triggers and wakes.
| Limit | What it holds | Default | Ceiling |
|---|---|---|---|
triggersPerAgent | Triggers one agent manifest's runtime.triggers declares, checked when it is saved. | 20 | One request body |
triggerMinIntervalMs | The shortest gap between two runs of one schedule, checked over its next fires when the manifest is saved. | 60 s | A number. Floor: 60 s, since a schedule is minute grained. |
triggerRunsPerHour | Runs one Agent's triggers start or queue in any hour. Later ones are skipped. | 60 | A number |
triggerJitterPercent | How far a schedule's fixed offset may move its runs, as a part of its interval. | 10 | 50 |
triggerJitterMaxMs | The most that offset may be. | 5 min | A timer |
triggerPromptChars | One trigger's prompt. | 8,000 | One record entry, escaped |
triggerRunRetentionMs | How long an Agent's runs are kept. | 30 days | A number. Floor: 24 h, since runs dedupe repeated fires. |
wakeMaxAheadMs | How far ahead schedule_wake may book a session's next turn. It must also be at least triggerMinIntervalMs ahead. | 30 days | A number |
wakeNoteChars | The longest note a booked wake carries to its turn. | 2,000 | One record entry, escaped |
webhookBodyBytes | The largest delivery a webhook endpoint reads, before it verifies it. | 256 KiB | 960 KiB: the payload goes into one record entry |
Memory
See Agent memory. Checked on every write.
| Limit | What it holds | Default | Ceiling |
|---|---|---|---|
memoryBytes | The largest memory, in UTF-8 bytes. | 100 KiB | 32 MiB: half a Harness API frame |
memoriesPerAgent | The most memories one Agent holds. | 10,000 | A number |
memoryIndexLines | The most lines of the memory index a session pins at its start. Newest memories come first. | 200 | A number |
memoryIndexBytes | The most UTF-8 bytes of that index. | 25 KiB | 16 MiB: a quarter of a Harness API frame |
Flows
| Limit | What it holds | Default | Ceiling |
|---|---|---|---|
flowConcurrency | Effects one flow turn runs at once. The rest wait their turn. | 8 | A number |
flowMapItems | Items one map stage fans out to. | 1,000 | A number |
flowLoopIterations | Iterations one loop stage runs. | 100 | A number |
Agent manifests
What one agent manifest may hold, checked when it is saved.
| Limit | What it holds | Default | Ceiling |
|---|---|---|---|
folderFiles | Files in one agent manifest. | 2,000 | One request body |
folderBytes | Bytes of an agent manifest's files together. | 50 MiB | A number |
folderTextFileBytes | One Markdown or JSON file of an agent manifest, which the compiler reads. | 1 MiB | About 512 MiB: one string |
npx nylorun check, npx nylorun apply, and packFolder() hold a folder to
these defaults whatever the Tenant sets, so raising them helps only a client
that uploads a folder itself, such as Studio's Upload folder….
Ceilings
A ceiling is what the Runtime depends on, not configuration:
| Ceiling | Value |
|---|---|
| One string | 536,870,888 characters (about 512 MiB), the longest string the JavaScript engine makes. A body the Runtime reads whole, or a file it sends in base64, is one string. |
| One request body, one response body | As many items as fit in one string, each at its smallest JSON. |
| One record entry | 960 KiB. A quoted text there is at most 163,840 characters ("escaped"), since JSON may escape a character to 6 bytes. |
| A Harness API frame | 64 MiB, the largest message between the Runtime and a harness. |
| A timer | 2,147,483,647 ms, about 24.8 days, the longest delay a JavaScript timer takes. |
| A number | 9,007,199,254,740,991, the largest whole number a JavaScript number holds exactly. |
Lower limits for one agent
An agent manifest's runtime section may set lower limits for the Agents made from it:
{
"$schema": "https://docs.nylorun.com/schemas/agent-folder/v1/runtime.json",
"kind": "pod",
"limits": {
"artifacts": { "fileBytes": 26214400 },
"disk": { "versionEntries": 50000, "versionBytes": 2147483648 }
}
}| Field | Within |
|---|---|
limits.artifacts.fileBytes | The Tenant's artifact fileBytes. The largest file one artifact upload, save, or export may store. |
limits.artifacts.totalBytes | The Tenant's artifact totalBytes. What its sessions' artifacts and its disk versions hold together. |
limits.skills.totalBytes | The Tenant's skill limit. What one skill's files hold together, for a session to open on it. |
limits.disk.versionEntries | The Runtime limit diskVersionEntries. |
limits.disk.versionBytes | The Runtime limit diskVersionBytes. |
In an agent manifest this is runtime.json; in a
manifest document, its runtime section. A value above the Tenant's is refused
when the manifest is saved, naming the limit. A limit left out is the Tenant's, as it is when the limit is checked. The Agent's limits
(client.agents.get(id)) shows what is in force for it now. See
Saving manifests.
Skill and artifact limits
Two other Tenant settings hold sizes, each a document with the same get and
put:
| Setting | Limits | Default | Set with |
|---|---|---|---|
| Skills | totalBytes: the most bytes one skill's files hold together. No per-file or file-count limit. A skill past it is 413 limit_exceeded (details.skills) when the manifest is saved. | 2 GiB | admin.settings.skills, nylorun tenant settings skills |
| Artifacts | fileBytes: the largest file one upload may store. totalBytes: what every artifact version holds together. The view adds usedBytes. | 100 MiB, 10 GiB | admin.settings.artifacts, nylorun tenant settings artifacts |
await admin.settings.skills.put({ limits: { totalBytes: 4 * 1024 ** 3 } });The Agents' compute settings, such as how many Agents a Tenant holds, are on Kubernetes.
Fixed values
Some sizes stay fixed because a dependency or a standard fixes them: a 1 MiB
record entry, the 64 MiB Harness API frame, and the longest JavaScript string
and timer; a token's size, since a bearer token or a capability link arrives in
a request's headers, and a page cursor's, which arrives in a URL; an artifact
name's 255 characters and a folder path's 1,024; a link target's 4,096; W3C
tracestate's 512 characters; a model-facing tool name's 64 characters, which
every provider takes; and a Content-Type's 255. Identifier lengths are part
of the protocol: an Agent's id and a subject 200, an agent manifest's name and
a credential's name 64, a harness id 63, an application key's id and an
issuer's name 32, an idempotency key 256.
Reference
| Call | Endpoint |
|---|---|
admin.settings.limits.get() | Get the Tenant's Runtime limits |
admin.settings.limits.put({ limits }) | Set the Tenant's Runtime limits |
admin.settings.skills.get() / .put() | Get the Tenant's skill limit, Set the Tenant's skill limit |
admin.settings.artifacts.get() / .put() | Get the Tenant's artifact limits, Set the Tenant's artifact limits |