> ## Documentation Index
> Fetch the complete documentation index at: https://docs.matrices.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect a service

> Give an agent a Linear login the model never gets to read.

To act in an outside service, an agent needs two things: a
[role](/model/roles) that grants the service's tools, and a
[connection](/model/connections) that holds the login. You'll set up both for
Linear. The model never sees the token.

## 1. Grant the provider tools

Managed providers get a namespace like any other toolset, so a role grants them
by name:

```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
export ROLE_ID="$(
  curl --fail --silent --show-error "https://api.matrices.com/v1/roles" \
    -H "Authorization: Bearer $MATRICES_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Linear user",
      "description": "Reads and files Linear issues.",
      "allow": ["tool:managed:linear.*"]
    }' | jq -er '.role.id'
)"
```

Add it to the agent's [profile](/model/profiles) the way
[Narrow an agent's permissions](/guides/narrow-permissions) does. The agent can
call the tools now, but every call fails until there's a login behind them.

## 2. Choose the owner

The owner decides which agents can use the connection:

* `workspace`: every agent in the workspace shares one login. Good for a bot
  account your whole product acts through.
* `identity`: only agents carrying that [identity](/model/identities). Dana's
  Linear login works for every agent acting for Dana, and no other agent can
  see it.

Pick `identity` whenever the login belongs to a person. You set that value when
you created the agent, and it can't change afterward.

## 3. Store the token

If the service authenticates with a plain API token, storing it is one request:

```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
export CONNECTION_ID="$(
  curl --fail --silent --show-error "https://api.matrices.com/v1/connections" \
    -H "Authorization: Bearer $MATRICES_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "provider": "linear",
      "name": "Research Linear",
      "owner": { "type": "identity", "identity": "svc:research" },
      "token": "lin_api_example"
    }' | jq -er '.connection.id'
)"
```

The `identity` here has to match the agent's exactly: `svc:research` for this
one, `email:dana@example.com` for an agent acting for Dana. Matrices encrypts
the token on the way in and never gives it back.

An OAuth provider has no token to paste. Connect from the dashboard, or let the
agent start the flow itself with the built-in `connections.connect` tool, which
needs `tool:builtin:connections.connect` in its role.

<Note>
  A server-to-server OAuth connect API is planned but not available yet. Token
  connections and every management endpoint here work today.
</Note>

## 4. Use it, and handle a broken login

Ask the agent to do something in Linear. Matrices finds a connection the calling
agent is allowed to use and attaches the login to the outgoing request:

```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
curl --fail --silent --show-error "https://api.matrices.com/v1/agents/$AGENT_ID/threads" \
  -H "Authorization: Bearer $MATRICES_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "content": [{ "type": "text", "text": "List the open Linear issues on the research board." }] }'
```

Logins break in two different ways. When the provider rejects an OAuth grant,
the connection flips to `needs_reauth`, meaning someone has to sign in again. A
static token never changes state: it stays `ready` while the calls fail. So when
you know one is dead, replace it, naming the version you expect to overwrite:

```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
curl --fail --silent --show-error -X PUT \
  "https://api.matrices.com/v1/connections/$CONNECTION_ID/token" \
  -H "Authorization: Bearer $MATRICES_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "token": "lin_api_rotated", "expectedVersion": 1 }'
```

To kill a login for good, `POST /v1/connections/{connectionId}/revoke` with its
`expectedVersion`.

## Check it worked

```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
curl --fail --silent --show-error -H "Authorization: Bearer $MATRICES_API_KEY" \
  "https://api.matrices.com/v1/connections?ownerType=identity&status=ready&limit=50" |
  jq -r '.connections[] | "\(.provider) \(.owner.identity) \(.status)"'
```

A `ready` row whose identity matches the agent's means the login half is done.
The role is the other half, and you need both:
`GET /v1/agents/{agentId}/effective-permissions` should list the `linear.*`
tools.

## Where next

<CardGroup cols={2}>
  <Card title="Approve a tool call" icon="hand" href="/guides/approve-a-tool-call">
    Ask a human before the agent sends anything.
  </Card>

  <Card title="Run on a schedule" icon="clock" href="/guides/run-on-a-schedule">
    Have it check Linear every morning without you.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.