Configuration reference
This page lists every setting of the runtime, the configuration file, and the tool servers functions may call. The runtime reads its settings once, when it starts. Change a setting, then restart the server.
How settings are read
- Every setting is an environment variable. Keys and other secrets go in the environment alone.
- A container takes its variables from its platform, or from a file of them with
docker run --env-file. npx @on.auto/runtimealso reads.envin the folder it starts in. A variable set in the shell wins over.env.- Settings that are lists or maps can also go in a YAML configuration file:
model_gateways,model_aliases,declared_models,allowed_models,tool_servers,connections,api_keysandallowed_origins. CONFIG_FILEnames that file.npx @on.auto/runtimereadsauto-runtime.yamlin the folder it starts in when it is there, unless.envor the shell setsCONFIG_FILE. A container reads a file only whenCONFIG_FILEnames it, as Use a configuration file shows.- Each key of the file stands for the environment variable of the same name in upper case. A variable that is set wins over the key, whole:
MODEL_GATEWAYSreplaces the file'smodel_gateways, and the two are not merged. - Precedence, highest first: the shell,
.env(withnpx), the configuration file, the default. - At start, the server logs which settings it read from the file, and which of them the environment set too.
- A value the server cannot read stops it at start. The message names the setting and what it expects, and never the value.
Write the configuration file
Copy auto-runtime.example.yaml to start one. auto-runtime.schema.json is the file's JSON Schema, so an editor with the YAML language server completes and checks it.
# yaml-language-server: $schema=https://raw.githubusercontent.com/BeOnAuto/runtime/main/auto-runtime.schema.json
model_gateways:
- name: gateway
base_url: https://gateway.example.com/v1
api_key: ${GATEWAY_API_KEY}
model_aliases:
anthropic/*: gateway/anthropic/*A secret is never written in the file. The file refers to the variable that holds it:
${NAME}takes the value of the variableNAME;${NAME:-default}takesdefaultwhenNAMEis not set;$$stands for a literal$.
The server stops at start with one line that names the file, the line, the column and the key, never a value, when:
- it cannot use the file;
- the file holds a key the server does not know;
- a value is one its setting refuses;
- a reference names a variable that is not set;
- a credential is written out instead of referenced.
A value counts as a credential written out when:
- its key names a credential, such as
api_key,Authorization,client_secret,passwordortoken, and it holds no reference.credential_kindsof theconnectionssection names sorts of credential and not one, so its values are judged by their shape alone; - the text written out in it has the shape of one, such as
Bearer ..., ansk-...provider key or anabk_...API key; - it is a URL with a password, whose user or query value has that shape, or whose query names a parameter as a key that names a credential does, such as
?api_key=..., and holds no reference there; - it is an argument whose part after its
=has that shape.
Inside an argument, only the value is judged, never the name the argument gives it.
What to set for what
| To use | Set | See |
|---|---|---|
| A provider's own API | ANTHROPIC_API_KEY, OPENAI_API_KEY or GOOGLE_GENERATIVE_AI_API_KEY | Direct API keys |
| An OpenAI-compatible gateway | model_gateways in the file, a list whose name becomes the prefix, gateway/<model> | A gateway |
| Amazon Bedrock | AWS_REGION, with the AWS default credential chain | Bedrock |
| Azure OpenAI | AZURE_RESOURCE_NAME and AZURE_API_KEY | Azure |
| Google Vertex AI | GOOGLE_VERTEX_PROJECT and GOOGLE_VERTEX_LOCATION | Vertex |
| Your own names for models | model_aliases in the file | Model aliases |
| Another provider's models, through your gateway | model_aliases: {anthropic/*: gateway/anthropic/*} in the file | Model aliases |
| The models listed for Bedrock, Azure or Vertex | declared_models in the file, a list of model ids for each provider prefix | Declared models |
| Only some models | allowed_models in the file, such as [anthropic/*, gateway/llama-3.3-70b] | Allowed models |
| An outbound proxy or a private certificate authority | NODE_USE_ENV_PROXY=1, HTTPS_PROXY and NODE_EXTRA_CA_CERTS | Proxy and CA |
| The ledger in Amazon RDS without a database password | DATABASE_URL without a password and DATABASE_CREDENTIALS=aws-iam | Without a password |
| Secrets sealed under a key of your own | SECRETS_KEY, and SECRETS_KEY_PREVIOUS while it replaces another | Secrets at rest |
| Content kept in an object store instead of the ledger | CONTENT_STORE_URL, an s3://bucket/prefix URL | Object storage |
| Tools that functions may call | tool_servers in the file, each entry's allowed to allow only some of its tools | Tool servers |
| People who sign in through the Auto identity service | PUBLIC_URL, which turns sign-in on, and IDENTITY_ISSUER for a development instance of the service | Let people sign in |
| Machines and pipelines that call the API | API_KEYS, with an entry the key command prints for each | API keys |
| The requests interaction functions may keep open | INTERACTION_OPEN_REQUESTS | Interaction functions |
| The model processes and the builds of prediction functions | PREDICTION_PROCESSES, PREDICTION_PROCESS_MEMORY, PREDICTION_BUILDS_AT_ONCE, PREDICTION_BUILDS_PER_DAY and PREDICTION_MAX_FUNCTIONS | Prediction functions |
| The folder prediction functions keep model files in | PREDICTION_CACHE_DIR | Prediction functions |
list_models (GET /v1/orgs/{org}/models, and the MCP tool of the same name) shows the models the server can call, leaving out what allowed_models does not allow. Listing the models sets out how it builds the list, and Allowed models what a definition that names a model outside allowed_models returns.
Settings
Every setting is an environment variable. The tables below group them by area.
Server and logs
| Variable | Default | Purpose |
|---|---|---|
PORT | 5555 | The port the server listens on |
HOST | 0.0.0.0 in the image, 127.0.0.1 with npx | The interface the server binds to. On a loopback address with neither PUBLIC_URL nor API_KEYS, the server is in local mode. On any other address it needs one of them to start |
CONFIG_FILE | none; auto-runtime.yaml with npx when it is in the folder | The configuration file, absolute or relative to the working directory |
LOG_FORMAT | json, console with npx | json: one JSON object per line on stderr. pretty: lines of text for a person. console: a time, a mark for the level and the message, in color at a terminal |
LOG_LEVEL | info, error with npx | The least level logged: debug, info, warn or error |
Sign-in and access
Authentication and security sets out how these work together.
| Variable | Default | Purpose |
|---|---|---|
PUBLIC_URL | none | The URL at which callers reach the runtime. Set, it turns sign-in through the Auto identity service on, and every access token names it as its audience. Let people sign in gives the URLs it accepts |
IDENTITY_ISSUER | https://clerk.on.auto | The identity service that people sign in through, an https URL with no path, query or fragment. A development runtime names the development instance of the service |
API_KEYS | none | The API keys the server accepts, as a compact JSON array of the entries the key command prints; api_keys in the file. See API keys |
ALLOWED_ORIGINS | none | Comma-separated origins a browser page may call the API from, besides Auto Studio's; allowed_origins in the file. See Calling from a browser |
Storage
| Variable | Default | Purpose |
|---|---|---|
LEDGER_FILE | data/ledger.db, which in the image is on the /data volume; ~/.auto-runtime/ledger.db with npx | The SQLite file of the ledger, absolute or relative to the working directory. Its folder is created when missing |
DATABASE_URL | none | A PostgreSQL URL. When set, the ledger is kept in that database instead, and setting LEDGER_FILE too stops the server at start. Environment only, since it holds a password. See Use PostgreSQL |
DATABASE_CREDENTIALS | url | How the server signs in to that database: url, with the password the URL holds, or aws-iam, with a token signed for each connection. See Without a password, on Amazon RDS |
SECRETS_KEY | secrets.key beside a SQLite ledger file, made at the first start | The key the secrets kept in the ledger's database are sealed under: the base64 of 32 random bytes, as openssl rand -base64 32 prints it. Without it, a SQLite ledger keeps a key in that file, which only its owner may read. A ledger in PostgreSQL needs it, and a container sets it. The server also derives from it the key that signs the state an MCP client sends back when it retries a call, so every server that shares it answers that retry. Environment only. See Secrets at rest |
SECRETS_KEY_PREVIOUS | none | The key that SECRETS_KEY replaces, in the same form and only beside it. At start the server reads with it what it sealed and seals that again under SECRETS_KEY, after which it can go. While it is set, the server also answers the retry of an MCP call whose state a server signed under the key it replaces. See Rotate the secrets key |
CONTENT_STORE_URL | none | An s3://bucket/prefix URL. When set, content is kept in that bucket instead of the ledger's database. Content kept before a change is not moved; see Keep content on object storage |
Models
Reasoning functions call language models with these settings, all optional. Set up a model provider says which to set for what, and how to check them in the start-up line. A provider whose settings are absent is not configured, and a definition that names it is rejected as unavailable when it runs. The model settings reference holds the rules for the lists and maps below.
| Variable | Purpose |
|---|---|
ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN, ANTHROPIC_BASE_URL | Anthropic (anthropic/...) |
OPENAI_API_KEY, OPENAI_BASE_URL, OPENAI_API | OpenAI (openai/...). OPENAI_API=chat_completions for endpoints without the Responses API |
GOOGLE_GENERATIVE_AI_API_KEY | Gemini API (google/...) |
AWS_REGION, AWS_BEARER_TOKEN_BEDROCK, AWS_ENDPOINT_URL_BEDROCK_RUNTIME, AWS_ENDPOINT_URL | Amazon Bedrock (bedrock/..., bedrock-anthropic/...), with the AWS default credential chain |
AZURE_RESOURCE_NAME or AZURE_BASE_URL, AZURE_API_KEY, AZURE_API_VERSION | Azure OpenAI (azure/...). Without a key, Microsoft Entra ID, in an image built with --build-arg AZURE_IDENTITY=true |
GOOGLE_VERTEX_PROJECT, GOOGLE_VERTEX_LOCATION | Vertex AI (vertex/..., vertex-anthropic/...), with Google application default credentials |
MODEL_GATEWAYS | A list of OpenAI-compatible gateways, each its own provider prefix; model_gateways in the file |
MODEL_ALIASES | A map from one model reference to another. A trailing * on both sides covers every model of a provider; model_aliases in the file |
DECLARED_MODELS | The models list_models shows for a provider that does not list its own, and for a gateway whose list cannot be read, by provider prefix; declared_models in the file |
ALLOWED_MODELS | The only model references a definition may give, by name or through an alias, and that list_models shows; every model when not set; allowed_models in the file |
NODE_USE_ENV_PROXY, HTTPS_PROXY, NO_PROXY, NODE_EXTRA_CA_CERTS | Node's own switches for an outbound proxy and a private certificate authority |
REASONING_MAX_INPUT_TOKENS | The most input tokens the model calls of one run of a reasoning function may add up to, from 10,000 to 9,999,999, 2,000,000 unless set. Past it, the model replies from what it has, without its tools |
Workflows
Workflow storage and failover sets out how the server uses these.
| Variable | Default | Purpose |
|---|---|---|
WORKFLOW_MAX_DURATION | P30D | The most a run may last, an ISO 8601 duration from PT2H to P365D |
WORKFLOW_NESTED_RUNS | 32 | How many calls the server runs at once, from 1 to 1000, shared by every org |
WORKFLOW_MAX_OPEN_CALLS | 1000 | How many calls may wait under one run at the top of a tree, from 1 to 9999 |
WORKFLOW_SWEEP_INTERVAL | PT1S | How often the server checks its waiting runs (a sweep), an ISO 8601 duration from PT0.01S to PT1M |
Telemetry
OTEL_EXPORTER_OTLP_ENDPOINT turns telemetry on, and TELEMETRY_CONTENT=true records content. Send telemetry lists these and the other OTEL_ settings the server reads. Each is read from the environment only.
Computation and recall functions
Each run of a computation function, and each run and view of a recall function, runs in a worker thread the server keeps between runs.
- The server never keeps more workers alive than
COMPUTATION_WORKERS. - It folds the views of recall functions in at most half of the workers at once, and at least one.
- It ends a worker after a run that ran past its time, used too much memory, was cancelled or broke.
- It also ends a worker after its thousandth run, and after a minute without one.
- A worker has a stack of 64 MiB and is stopped when its heap grows past 256 MiB. Plan memory sizes them.
| Variable | Default | Purpose |
|---|---|---|
COMPUTATION_WORKERS | 4 | The most worker threads the server keeps, and so the most runs it takes at once, from 1 to 64. A run that finds none free within 10 seconds is unavailable |
RECALL_MAX_FUNCTIONS | 32 | How many active recall functions a playbook may keep, from 1 to 1000. Lowering it below what a playbook already keeps refuses only that playbook's saves |
RECALL_MAX_REBUILDS | 4 | How many views of one playbook are built at once, from 1 to 64. The others wait in the order they were saved |
RECALL_PLAYBOOKS_AT_ONCE | 4 | How many playbooks the server folds at once, from 1 to 64 |
Interaction functions
An interaction function needs nothing configured beyond its tool server in tool_servers. It does one of these:
- calls the tool it names under
call, and returns its result; - sends its request through the tool it names under
deliver; - leaves its request in the playbook's inbox.
It may also read the replies to what it sent through another tool of that server.
- The entry's
allowednames the tools its functions may use. It is checked again at every call, every attempt and every read. - The entry's
record_content, on unless the entry turns it off, keeps what they send and what the tool returns.
| Variable | Default | Purpose |
|---|---|---|
INTERACTION_OPEN_REQUESTS | 10000 | The most requests a playbook may have open at once, from 1 to 1,000,000. A run past it is unavailable with the kind requests_full |
Prediction functions
A prediction function's content is kept by the playbook: its uploaded datasets, the rows and the brief of each build, and the model file each version holds. That content is in the ledger's database or, with CONTENT_STORE_URL, in the object store, where a build's candidates are also staged until the build ends.
Its model processes load models and read a build's rows from files the server keeps on its own disk. The server writes a file again from the playbook's content whenever one is missing, so the folder needs no volume and loses nothing when it is emptied.
Each setting is read with its range and logged at start. A value outside its range stops the server at start, naming the setting. Plan memory sets out how much the processes take.
| Variable | Default | Purpose |
|---|---|---|
PREDICTION_MAX_FUNCTIONS | 32 | The most active prediction functions a playbook may keep, from 1 to 1,000. A save past it is refused |
PREDICTION_PROCESSES | 4 | The most model processes that run at once, from 2 to 64 |
PREDICTION_PROCESS_MEMORY | 1280 | The data each model process may reserve, in MiB, from 768 to 16,384. A process that reaches it is ended, and its job ends out of memory |
PREDICTION_BUILDS_AT_ONCE | 2 | The most builds the server scores at once, from 1 to 63, and below PREDICTION_PROCESSES so that a question always finds a process. A build past it is unavailable with the kind builds_full |
PREDICTION_BUILDS_PER_DAY | 4 | The most builds a prediction function may ask in the trailing 24 hours, from 1 to 100. A build past it is unavailable with the kind builds_full and the because field builds_of_the_day |
PREDICTION_CACHE_DIR | /var/tmp/auto-runtime | The absolute path of the folder the model files are kept in |
The folder of PREDICTION_CACHE_DIR follows these rules:
- At start, the server creates the folder when it is missing, readable only by its own user, and does the same for each folder within it.
- It refuses to start, naming the setting, when the folder cannot be made, belongs to another user, or other users may write to it. A folder another user may write to would let that user change a model before it is loaded.
- The files found in the folder at start are read again, and kept only when their bytes match the digest in their name.
- Each server keeps at most 1 GiB of model files and 1 GiB of rows, by its own count. Give two servers on one machine a folder each.
Tool servers
A tool server gives functions tools to call. It comes from one of two places: an entry under tool_servers in the configuration file, which this section describes, or a connection a person added to an org. Add an entry under tool_servers; TOOL_SERVERS, the same list as JSON, wins over it. Add a tool server walks through adding one and checking it.
- A reasoning function that lists
toolscalls the tools of these servers. - An interaction function calls the tool it names in
call, or sends its request through the tool it names indeliver. - The key of an entry is the name a function writes in
server/tool. Nothing in a function says which kind of server it names.
Each entry is one of three types. When type is left out, it is taken from the field that names the server:
| Type | Named by | What it is |
|---|---|---|
mcp | url | A remote MCP server, spoken to over Streamable HTTP |
stdio | command | An MCP server the runtime runs as a process |
openapi | document | An HTTP API described by an OpenAPI document, 3.0 or 3.1, read once at start. Each of its operations is one tool |
tool_servers:
graph:
url: https://gateway.example.com/mcp
headers:
Authorization: Bearer ${GRAPH_API_KEY}
org: acme
playbooks: [sales, support]
allowed: [search, introspect, validate, dry_run, execute]
notes:
command: /usr/local/bin/notes-mcp-server
args: [--read-only]
env:
PATH: /usr/local/bin:/usr/bin
NOTES_API_KEY: ${NOTES_API_KEY}
org: acme
billing:
document: https://billing.example.com/openapi.json
base_url: https://billing.example.com/v2
security:
apiKeyAuth: ${BILLING_API_KEY} # the scheme the document declares under components.securitySchemes
headers:
X-Tenant: acme-eu # outside the document's schemes
org: [acme, globex]
allowed: [listInvoices, getInvoice]Fields of an entry
| Field | For | What it holds |
|---|---|---|
type | every type | mcp, stdio or openapi. Taken from url, command or document when left out |
url | mcp | The server, spoken to over Streamable HTTP |
headers | mcp, openapi | Headers sent with every request. For an mcp server, its credential. For an openapi server, only what its document's security schemes do not place, such as a tenant. The value of a reference is a secret; a value written out is not |
auth | mcp, openapi | OAuth client credentials instead of a header: issuer, client_id, client_secret or private_key with algorithm, and scope. For an openapi server, what satisfies the document's oauth2 and openIdConnect schemes; refused when it declares neither. See Sign in to a server with OAuth |
command | stdio | An installed, pinned command, started when a run or a listing first needs it and stopped with the server |
args | stdio | Its arguments |
env | stdio | Its whole environment. The value of a reference is a secret; a value written out is not. It inherits nothing else from the server, so give PATH or an absolute command |
document | openapi | The OpenAPI document of the API, 3.0 or 3.1, in JSON or YAML: an https URL, an http URL on a loopback address, or a path relative to the directory of this file that stays inside it |
base_url | openapi | The URL the calls go to, in place of the first server the document names. Required when the document names none or names it relative to a file. An https URL, or an http URL on a loopback address |
query_params | openapi | Query parameters sent with every call that the document's security schemes do not place, such as a tenant. The value of a reference is a secret; a value written out is not |
security | openapi | The credential for each of the document's security schemes that the entry gives, by the scheme's name, placed where the scheme says. Always a reference, such as ${BILLING_API_KEY} or ada:${BILLING_PASSWORD}. See The credentials of an HTTP API |
org | every type | Required. The org whose functions may use the server, a list of orgs, or * for every org of the runtime. One entry serves each org under one name, with one credential and one connection, and each org sees the same tools |
playbooks | every type | The playbooks that may use it within each org it names, by id, the same list in each. Every playbook of each org when left out. Refused beside *, since a playbook id belongs to one org |
allowed | every type | The tools of the server that a function may name and that a call made by hand with execute may call, each named as the server lists it, without the server's name and without *. Every tool of the server when left out |
record_content | every type | Whether the arguments and results of calls are kept whole, scrubbed of secrets, in the playbook's ledger, where anyone who may read the playbook reads them. true when left out; false keeps their sizes alone |
request_id | every type | The response header, or for an MCP server the key of a result's metadata, in which the server returns its own id of a request, recorded with each call |
Keep secrets out of the file
Only headers, query_params, security, env and auth may hold a reference. A reference in url, command, args, document or base_url stops the server at start: an argument shows in the machine's list of processes, and the URL of a server or of a document is no place for a credential.
A secret is one of these, and nothing else:
- a value a
${NAME}reference takes from the environment; - a credential of an
authblock; - a token minted from one.
A value of security, which always holds a reference, is a secret as a whole, and so is the value of its reference. A header whose reference takes a scheme and a credential, such as Authorization: ${GRAPH_HEADER} with GRAPH_HEADER set to Bearer <key>, is a secret whole, and so is the credential after its scheme, <key>, so it is scrubbed where a server echoes the key alone. Each secret counts once, however many places hold it. A header written out, such as X-Region: production-eu, is not a secret, so it is never scrubbed.
The server scrubs every secret from every message, event and result:
- as written;
- inside JSON, where a quote, a backslash or a line break in it is escaped;
- as an address carries it, form-encoded in a query and percent-encoded in a path;
- in base64, as a Basic credential carries it.
There is one exception: a value shorter than 8 characters is not scrubbed, since scrubbing it would erase ordinary words. Give a server a key at least that long.
One set of secrets serves all the tool servers, for runs and for calls made by hand with execute alike, so a token minted for a run is scrubbed from a call made by hand too. A minted token is scrubbed until the token after the one that replaces it is minted, since a call in flight as a token is renewed may still carry the one before it in a result recorded a moment later.
Run a server as a process
- Write
commandas an installed program. Never use a package downloaded at start, such asnpx -y, which would run whatever that package is the day the process starts. The MCP entry of the quick start is the one exception: it is Auto Runtime itself, pinned to one release, and you choose when to move it to another. - The process runs under the server's user.
envis the process's whole environment, so give itPATHor writecommandas an absolute path.
Sign in to a server with OAuth
An auth block gives an mcp or openapi server OAuth client credentials instead of a header.
- The server mints tokens from the client credentials, once for every run that needs one.
- It renews them before they expire, and mints once more when the server responds with
401. - It sends the credentials only to an authorization server whose metadata names the
issuer. - An
mcpserver's authorization server is found through the server's own protected-resource metadata. - An
openapiserver's authorization server is theissueritself. Its metadata is read by OAuth authorization server metadata or OpenID Connect discovery, since an HTTP API publishes none of its own.
The credentials of an HTTP API
Give an HTTP API's credential under security, by the name of the security scheme its document declares. The server places it as the scheme says.
An OpenAPI document declares its security schemes under components.securitySchemes, each saying where its credential goes. Each operation names the schemes it requires under security, or takes the document's own security when it names none.
| Scheme | What security gives | What a call sends |
|---|---|---|
apiKey in a header | the key | the scheme's header |
apiKey in the query | the key | the scheme's query parameter |
http with the scheme bearer | the token | Authorization: Bearer <token> |
http with the scheme basic | user:password | Authorization: Basic and their base64 |
oauth2 or openIdConnect | nothing: the entry's auth block | the token the block mints, as a bearer |
Use security for what the document's schemes describe, and headers and query_params for what they do not, such as a tenant.
Which credentials a call sends:
- A requirement is a list of alternatives. Each alternative is a set of schemes that must all be given.
- An operation is offered as a tool when the entry gives one of its alternatives.
- A call sends the credentials of the first alternative the entry gives, in the document's order, and no other.
- An operation whose requirement is empty, or of a document that declares none, sends none.
- An operation for which the entry gives none of the alternatives is not offered as a tool. At start, the server logs a warning that names the schemes it needs.
- The scopes an
oauth2requirement names are the operation's. Theauthblock asks for its ownscope, so set it to cover what the operations require.
The server stops at start, naming the entry, when:
- a name under
securityis not a scheme the document declares; - a name under
securityis anapiKeythe document places in a cookie; - a name under
securityis anhttpscheme other thanbearerandbasic; - a name under
securityis amutualTLSscheme; - a name under
securityis anoauth2oropenIdConnectscheme with a value, since the credential for those schemes comes from theauthblock; - a
basicvalue is notuser:password; headersorquery_paramsholds a header or query parameter that a scheme given undersecurityalso places;- an entry has an
authblock, and its document declares nooauth2oropenIdConnectscheme.
How an HTTP API becomes tools
At start the server reads each openapi entry's document: at most 4 MiB and 500 operations, within 10 seconds. It stops, naming the entry, when:
- it cannot read the document;
- the document's URL responds with a redirect, which the server does not follow;
- the document is Swagger 2.0, or of another version than 3.0 or 3.1;
- a part it reads is not of the shape the specification gives it (the message names the place in the document);
- two operations would share a tool name;
- a path does not begin with
/, which would join the host or the port ofbase_url; - a path holds a
.or..segment, a?or a#; - its tools take more than 16 MiB when listed;
- a reference does not resolve inside the document. This includes a reference to an http, https or file address, which the server never fetches;
- its calls would have nowhere to go: no
base_urland no server, or a server that is neither https nor on a loopback address.
Trailing slashes on base_url or on the server's URL are dropped.
Each operation becomes one tool:
- Its name is the
operationId, with any character a tool name cannot hold as_. Without one, it is the method and the path in lower case, such asget_invoices_idforGET /invoices/{id}. - Its description is the operation's
summaryanddescription. - Its input is one object: each path and query parameter by its name, and
bodyfor a JSON request body, each required when the document says so. The schemas ofcomponentsthey refer to are held inside it, so a function's model reads one schema whole. GETandHEADare read-only,DELETEdestructive, andGET,HEAD,PUTandDELETEidempotent. Soallowed,searchand a run's read-only calls read an API's tools as they read an MCP server's.
Some operations are not offered as tools. At start, the server logs a warning for each operation it leaves out, naming the entry and the reason. It leaves out an operation that:
- needs a header or a cookie;
- takes an object in its query;
- takes a body that is not JSON;
- is a
TRACE, or aGETorHEADthat takes a body; - has a path parameter of a
styleother thansimple; - has a query parameter of a
styleother thanform, or withexplode: false; - has an input schema of more than 64 KiB.
A call:
- fills the path and the query, with an array sent as repeated keys;
- refuses a path argument that is empty, holds a
/, or is.or..; - sends nothing to an address that would leave the origin or the path of
base_url; - sends the body as JSON, with the entry's headers and query parameters.
The response is read as the result of an MCP server's call is read, within the same bounds:
| The API responds with | The call's result |
|---|---|
| JSON | The tool's structured content, and its text |
| Text | Text |
| Any other media type | Noted, and not shown |
401 | A key the server refused |
429 | Waits out a Retry-After that fits |
5xx | A failing server |
| A redirect | An error result with its status. It is not followed, so the entry's headers and token go to no address but its own |
Any other response, including 404 | An error result carrying the API's response |
Listing an HTTP API's tools asks the API nothing: the document is the list.
Limit the tools a function may use
allowed narrows what a function may name, as allowed_models narrows the models. A server's own policy remains the hard boundary.
- A function's
server/*offers exactly the tools its server's entry allows. allowedis the one list of a server's tools. The five operations over the playbook's tool servers,search,introspect,validate,dry_runandexecute, show and call the tools it allows and no other.
Try the tools by hand
An agent or a person can look at a server's tools, and call one, before a function names it.
searchshows anyone who may read a playbook the entries that serve it, with the tools that each entry lets functions name. At the org level, a caller who may read every playbook of the org (withorg:readorplaybook:read) sees every entry that serves the org, whether the entry names the org inorgor uses*. Each comes with itsplaybooks(["*"]when they are left out).searchanddry_runsay whether the server marks a tool read-only (readOnlyHint).searchandintrospectadd no header, environment value, URL, command or credential of their own. What a server writes is passed on with the secrets above scrubbed out, except values shorter than 8 characters.executecalls one tool as a run would, under the entry's credential, which is the playbook's. So it needsplaybook:writewhatever the tool does, and it is live.- While a tool server is configured,
executeis marked destructive, so a client that honours the MCP hints asks the person before a call. - Every call made with
executeis recorded in the playbook's history under the caller, with its content where the entry keeps it.
Tool servers in the HTTP reference sets out the routes, fields and permissions of the five tools.
What the server checks at start
The server checks every entry at start. It stops at any of these, naming the setting and the place but never a value:
- an entry with none of
url,commandanddocument, or with more than one; - the fields of another type;
- a name that is not 1 to 32 lowercase letters, digits and hyphens starting with a letter;
- a name with two hyphens together or one at the end, which would blur where the server's name ends in the
server__toola model sees; - the name of a model provider or gateway;
- a missing
org; - a credential written out instead of referenced. This includes a password in a
url, and a user, a query value or the part of an argument after its=that looks like a credential, such as--key=sk-live-.... The value is judged, never the name it is given; - a reference outside
headers,query_params,security,envandauth; - a value of
securitywritten out instead of referenced; - an
Authorizationheader beside anauthblock; - a header the runtime sets itself;
- an
issuer, abase_urlor adocumentURL that is neither https nor on a loopback address; - a
base_url, or a first server of a document, with a query or a fragment; - a
documentpath that leaves the directory of this file; - in
allowed, an empty list, a name listed twice, a*, or a name that is not a tool name of 1 to 128 letters, digits, underscores, hyphens and dots (such asgraph/search).
An unknown key in an entry is refused, like any other unknown key.
The server does not connect to an MCP server or start a process until a run needs one, or until search, introspect, validate, dry_run or execute asks it for its tools. The servers' messages, a process's output on stderr and every failed call go to the server's log, scrubbed of the entry's secrets.
Connections
A connection is a tool server that a person adds to an org through their agent, which every playbook of the org may use, or the playbooks it names; a function names it by name/tool as it names an entry of tool_servers, and calls it in the same way. Let people add connections sets out how a person adds and approves one, and what a connection that is not ready answers. The connections section of the configuration file says what people may add; CONNECTIONS, the same object as JSON, wins over it. Every rule has a default, so leaving the section out lets people add any connection but one of the credential reference, which names no variable until variables lists it.
connections:
people_may_add: true
allowed_hosts: ['*.example.com', 'crm.example.com']
credential_kinds: [none, reference, secret, client_credentials]
variables: [CRM_API_KEY]| Key | Default | Purpose |
|---|---|---|
people_may_add | true | false refuses every new connection, and the runtime uses none already added, though list_connections still lists them as they are |
allowed_hosts | every host | The hosts a connection may reach, each a host or *. and a host for every host under it; the host of an mcp connection's url, of an openapi connection's document and base_url, and of the issuer of client credentials. Left out, a connection may reach every host, addresses inside your network such as localhost or 10.0.0.5 among them |
credential_kinds | every kind | The kinds of credential a connection may take: none, reference, secret and client_credentials |
variables | none | The environment variables a reference credential may name, such as CRM_API_KEY. None of them may be a variable the runtime reads for itself: any variable this page lists, such as SECRETS_KEY, API_KEYS, PUBLIC_URL or a provider's key; a credential the cloud libraries read, such as AWS_SECRET_ACCESS_KEY, AZURE_CLIENT_SECRET, AZURE_CLIENT_CERTIFICATE_PASSWORD or AZURE_PASSWORD; a gateway's api_key_env; or a variable that a reference of this file or of TOOL_SERVERS names |
add_connection refuses with 403 a connection one of these rules does not take, with the sentence of the rule, and with 409 a connection named as an entry of tool_servers. A key the section does not know, a pattern that is not a host, a kind there is not and a variable the runtime reads for itself stop the server at start, naming the line.
The rules are read at start, and checked again when a connection is first used after it, so a rule you change reaches a running server when it starts again: a connection a rule no longer takes is refused with the rule's sentence, which search shows, and with people_may_add: false the runtime uses no connection already added, in the sentence This runtime uses no connection: its operator sets up its tool servers itself. allowed_hosts holds every request a connection makes, not only those to the addresses it names: the server an openapi connection's document names, where base_url is left out, is checked once the document is read, and every request is checked before it is sent, those to an authorization server and those a redirect leads to among them. A call of an HTTP API follows no redirect, and the MCP client follows one only within the origin it asked. The value of each variable variables lists is read at start too, so a variable you set reaches a running server when it starts again.