---
title: "Let people add connections"
description: "Describe how you want the work done. Auto builds a working playbook you can test, change and run again."
url: "https://on.auto/docs/self-host/connections"
last_updated: "2026-10-17T15:17:42Z"
---

# Let people add connections

A connection is a tool server that a person adds to an org through their agent, rather than one you set up in Auto's settings file. The org owns it, and every playbook of the org may use it, or only the playbooks it names. The person approves it, and gives its credential where it takes one, on a page of Studio. The agent never sees the credential.

This page is for whoever runs Auto. It says how a connection is added, what it holds, how a function uses it, and the rules you set for it in `auto-runtime.yaml`. A tool server you set up yourself is still added as [Add a tool server](https://on.auto/docs/self-host/tool-servers) shows.

## How a person adds a connection

1.  The person asks their agent to connect a tool server, such as their CRM. The agent calls `add_connection` with the server's address, its options and how it is credentialled, never the credential itself.
2.  Auto keeps the connection, `pending`, and answers with a link to Studio's page, `https://studio.on.auto/connect`, which lasts ten minutes. An agent whose client opens links asks the person to open it; any other agent gives the person the link from its answer.
3.  On the page, signed in, the person approves the connection. Where it takes a secret or client credentials, the person types the credential there, and giving it approves the connection. The connection is then `connected`.

On a runtime that signs people in, only the person who added a connection may approve it, signed in as themselves. In [local mode](https://on.auto/docs/self-host/security#local-mode), the link alone binds: whoever holds it within its ten minutes approves the connection. A link is gone after its ten minutes, and nothing gives a pending connection another, so the way on is to remove the connection and add it again.

`list_connections` shows the connections of the org and whether each is `pending`, `connected`, `broken` or `removed`, which is how an agent sees whether the person approved one; `get_connection`, served over HTTP alone, reads one by its id. `remove_connection` removes one for good: no playbook may use it any more, and Auto forgets its credential. An org holds at most 50 connections that are not removed; `add_connection` refuses another with `409`, `conflict` of the kind `connections_full`, until one is removed. The [MCP reference](https://on.auto/docs/reference/mcp#connections) describes the three tools, and the [HTTP reference](https://on.auto/docs/reference/http#connections) the routes, those of Studio's page among them.

## How a function uses a connection

A connected connection is a tool server of its org, for every playbook of the org or the playbooks its entry names. A function names its tools as it names those of any tool server, by the connection's name and the tool, as in `crm/search` or `crm/*`, and calls them in the same way, with the same bounds and the same scrubbing of its credential from everything Auto records. `search` lists it beside the tool servers of the settings file, with `connection`, its id, and `introspect`, `dry_run` and `execute` reach it. Each call it records, a run's, one made by hand with `execute` and one an interaction function makes in a conversation, names the connection's id beside the server's name as `connection_id`, so the history stays plain once another connection takes the name.

A connection that is not ready is refused, and `search` lists it unavailable with the same words:

| The connection | A function that names it is refused with | Its words say |
| --- | --- | --- |
| Nobody has approved it yet | `connection_pending` | The person who added it opens its link, or removes it and adds it again for a new link |
| Its credential cannot be read | `connection_broken` | Why, and that the person who added it removes it and adds it again |
| A rule of `auto-runtime.yaml` no longer takes it | `connection_not_allowed` | The rule, in the sentence `add_connection` would give |
| `people_may_add` is now `false` | `connection_not_allowed` | That this runtime uses no connection, since you set up its tool servers yourself |
| Its entry is no longer one Auto takes, as when a model provider you set up since has its name | `connection_not_allowed` | What `add_connection` would refuse in it |
| Its `reference` names a variable that is not set | `connection_not_allowed` | The variable, and that you set it and start Auto again |
| Its name is that of a tool server of the settings file, for any org, which a later edit added | `connection_not_allowed` | That the settings file sets up a tool server of that name, and that it is removed and added again under another name |
| Its document names a server, or a call meets a redirect or an authorization server, on a host the rules do not allow | `connection_not_allowed` | The rule |

Each comes as `unavailable` of the kind `tool_not_offered`, before the function calls anything. A name that is neither a tool server of the settings file nor a connection of the org stays `tool_server_not_configured`.

Auto checks the rules, and checks the entry as `add_connection` checks it, when a connection is first used after Auto starts, once for each connection, and reads its credential then. A rule you change reaches a running Auto when it starts again. A connection Auto cannot read the credential of is broken for good: Auto records why, and the person removes it and adds it again, since nothing mends a broken connection. Where Auto cannot record it broken, it logs why, refuses it all the same, and reads the credential again at its next use, recording the break again.

Auto places the credential in the entry as the settings file places a reference to an environment variable, and reads the entry as it reads one of the file, with the same checks and the same secrets to scrub; the entry itself is sent as it is written, a `$` in it too. The document of an HTTP API is read when a function first uses the connection. A document that cannot be read just now, because its address does not answer in time, answers an error or answers a page that is no document, such as a proxy's error page, is read again at the next use; one refused for what it says stays refused until Auto starts again, and the person removes the connection and adds it again once the document is put right.

## Which runtimes take connections

A person approves every connection, so a connection is added by a person, and a runtime takes connections only where a person reaches it as themselves:

| Runtime | Who adds a connection | The runtime the link names |
| --- | --- | --- |
| One that signs people in, with `PUBLIC_URL` set | A person, through an agent signed in as them. `add_connection` refuses a key with `403`, since no person would approve what it adds | `PUBLIC_URL` |
| One in [local mode](https://on.auto/docs/self-host/security#local-mode) | The local developer | The runtime's loopback address |
| One of `API_KEYS` alone, which signs nobody in | Nobody: `add_connection` refuses every connection with `403`, since no person could approve it. Set `PUBLIC_URL` to sign people in, or add the server to `auto-runtime.yaml` as [Add a tool server](https://on.auto/docs/self-host/tool-servers) shows |  |

## What a connection holds

A connection has a name, which a function will give it as a tool server's name, a kind, an entry and a credential.

| Part | What it holds |
| --- | --- |
| `name` | 1 to 32 lowercase letters, digits and hyphens, starting with a letter. It may not be the name of a tool server of the settings file, nor of another connection of the org that is not removed |
| `kind` | `mcp` for a remote MCP server, `openapi` for an HTTP API described by an OpenAPI document |
| `entry` | The server without its credential: `url` for `mcp`, or `document` and `base_url` for `openapi`, with `headers`, `query_params`, `allowed`, `playbooks`, `record_content` and `request_id` as an [entry of the settings file](https://on.auto/docs/self-host/configuration#tool-servers) has them |
| `credential` | How the server is credentialled, below, never its value: one object, its `kind` and the fields that kind takes |

Auto checks an entry as it checks an entry of the settings file, and refuses one that holds a value that looks like a credential, or a reference to an environment variable such as `${CRM_API_KEY}`. A connection's `url` and document are each an `https` URL, or an `http` URL on a loopback address; a document is never a file on Auto's disk.

## The kinds of credential

| Kind | What the person gives | Where the value is kept |
| --- | --- | --- |
| `none` | Nothing; the server takes no credential | Nowhere |
| `reference` | Nothing; `variable` names an environment variable of Auto, such as `CRM_API_KEY`, that you set and list in the rule `variables`, and `name` and `in` say where its value goes, as for a `secret` | In Auto's environment, where you put it |
| `secret` | A key or token, on Studio's page. `name` and `in` say where it goes: `in: header` and the header's name, never one Auto sets itself such as `Content-Type`, `Host` or `Mcp-Session-Id`, or for an HTTP API `in: query` and a query parameter's name, or `in: security` and a scheme of its OpenAPI document | Sealed in Auto's secret store |
| `client_credentials` | The client secret, or a private key with its algorithm, on Studio's page. `issuer`, `client_id` and `scope` name the authorization server and the client | Sealed in Auto's secret store |

Auto seals a secret under its secret key, `SECRETS_KEY` or the key file beside a SQLite ledger, as [the configuration reference](https://on.auto/docs/self-host/configuration#storage) sets out. No record of the org, no answer and no history holds the value, and the link's token is kept only as its SHA-256. Of a secret or a client secret of twelve characters or more, Auto also keeps its last four characters beside the sealed value in the secret store, never in the org's record, and `list_connections` and `get_connection` answer them as `credential_ends_with`, so the person can tell which key a connection holds; a private key, or a shorter value, has none. Removing a connection forgets its secret, and the ending with it.

Every value of a credential is a secret Auto scrubs from what it records and answers, in each form it may take, as it scrubs the value of a reference of the settings file. A value in a header that is a scheme and a credential, such as `Bearer <token>`, is scrubbed whole and its credential alone.

A secret is only as recoverable as the key it was sealed under. When the key is lost, Auto can no longer read the credentials sealed under it, so their connections are broken. Auto marks such a connection `broken` when it first needs the credential, with a sentence that says why; the person removes it and adds it again.

## Set the rules in `auto-runtime.yaml`

A `connections` section of `auto-runtime.yaml` says what people may add. Every rule has a default, so a file without the section lets people add any connection but one of the credential `reference`.

```yaml
connections:
  people_may_add: true
  allowed_hosts: ['*.example.com', 'crm.example.com']
  credential_kinds: [none, reference, secret, client_credentials]
  variables: [CRM_API_KEY]
```

| Rule | What it does | When left out |
| --- | --- | --- |
| `people_may_add` | `false` refuses every new connection, and Auto uses none of those already added: `list_connections` still lists them as they are, `connected` among them, and a function that names one is refused. You set up every tool server yourself | `true` |
| `allowed_hosts` | The hosts a connection may reach. A pattern is a host, or `*.` and a host for every host under it, so `*.example.com` takes `crm.example.com` and not `example.com`. Auto checks the host of an `mcp` connection's `url`, of an `openapi` connection's `document` and `base_url`, and of the `issuer` of client credentials, where the client secret or the key's assertion goes, and then every request a call makes before it is sent | Every host, addresses inside your network such as `localhost` or `10.0.0.5` among them, so set it wherever a connection must not reach those |
| `credential_kinds` | The kinds of credential a connection may take, of the four above | Every kind |
| `variables` | The environment variables a `reference` may name. A reference sends the value of a variable of Auto to the server the person names, so you list each one a connection may send; Auto refuses to start on a list that names a variable it reads for itself, such as `SECRETS_KEY`, `API_KEYS` or a provider's key | None, so every `reference` is refused |

`add_connection` refuses a connection a rule does not take with `403`, saying which rule, such as `A connection may not reach the host api.billing.example.org on this runtime, which allows *.example.com and crm.example.com`. A connection added before a rule changed is refused the same way when it is first used after Auto starts again, `connection_not_allowed` with the same sentence. A rule the file gives that Auto cannot read stops it at start, naming the line. `CONNECTIONS`, the same rules as JSON, wins over the file. The [configuration reference](https://on.auto/docs/self-host/configuration#connections) lists the section.

`allowed_hosts` holds more than the addresses a connection names: the server an HTTP API's document names, where `base_url` is left out, is checked once Auto reads the document, and every request a call makes 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.

## Sitemap

See the [full documentation and product sitemap](https://on.auto/sitemap.md) for related pages.
