Set up credentials
Every agent signs in to your tools with credentials of its own, and the office needs a few as well. Outstaff never stores them (0008); ost setup tells you what to create, writes a template of the keys, and looks up every value you would otherwise copy by hand. This page is the flow. The list of every key is in the container contract.
Before you start
Section titled “Before you start”-
A team file with the integrations you use.
ost setupreads the adapters fromintegrationsand the repositories and grants fromreposandpeople. -
A secrets directory that git ignores. By default it is
.outstaff/secrets/next to the team file: one folder per scope,.outstaff/secrets/<handle>/for each person and.outstaff/secrets/office/for the office, with one file per key, named after the key. A container reads one such folder from/run/secrets/outstafforOUTSTAFF_SECRETS_DIR(secrets are files first). Add this to.gitignore:.outstaff/secrets/.outstaff/**/.env
Run ost commands from anywhere inside the repository: without --team, the team file is the first .outstaff/team.yaml or team.yaml found in the current directory or a parent, up to the git root. ost setup writes below the project root (the folder that holds .outstaff/); --out picks another one.
ost setup refuses to run until git ignores the .env file it names and the secrets directory it will use (if that is inside the repository), and prints the lines to add. ost init already adds both rules.
A new person
Section titled “A new person”Add the person to people in team.yaml with their repo grants (ost hire does this and runs the next step for you, see Hire and remove people), then:
ost setup samThis writes .outstaff/people/sam/.env.example and prints a guide per adapter. The template lists every key the configured adapters need for that person, each with what it is, where to get it, whether it is optional and whether it is derivable. It also shows where the secret files go. It never contains a real value.
Follow the guides in order:
- Slack. Create the app from the printed manifest (Socket Mode, the scopes and events the adapter uses), create the app-level token and install the app. Keep
SLACK_APP_TOKENandSLACK_BOT_TOKEN. - GitHub. What this step asks for follows the person’s repository grants. With no grants (a product manager or a designer who works in tickets, documents and chat), there is nothing to do: no GitHub keys are listed,
ost doctorskips GitHub, and the agent starts without a code host. With read grants only, the office App’s keys are required and the person’s own App is optional. With any write grant, create the person’s GitHub App with the printed permissions, install it on exactly the repositories the person can write (reads come from the office App), generate a private key and keep the App id and key; agents also hold the read-only office App’s keys, to clone repositories they may only read. The printed permissions include Actions: read, so the agent can read why a CI job failed (ost pr checks); the office adds it to that person’s token when the installation has it. If the person’s role declares thevcs.workflowscapability (the stock devops role does), the printed permissions also include Workflows: read and write. Without it GitHub rejects a push that touches.github/workflows/with “refusing to allow a GitHub App to create or update workflow”. Mind the risk: a workflow can read the repository’s Actions secrets when it runs, so give Workflows only to roles that change CI. Other roles keep it off; on a repository with.github/workflows/,ost doctorwarns that such a person’s App lacks it, because any change there would be refused and the agent would hand back blocked. Grant it, or leave the warning if that person must never change CI. Granting it on the App is your decision; when the installation has it, the office adds it to that person’s write token automatically. - Tracker. Agents are real members of the tracker, so people can assign work to them. See Its a Plan for what the adapter uses. The tracker is invite-only, so there is one human step, once per agent:
- Pick the agent’s address. Plus-addressing on a human’s mailbox is the default:
alex+sam@acme.exampledelivers toalex@acme.example. Or use a forwarding scheme on a domain your team owns, for example Cloudflare Email Routing:sam@agents.acme.exampleforwarded to a human. Setemail.patternin the team file to the scheme and the guide uses it. Outstaff does not run a mailbox. - Invite that address to the team and the project. The invite arrives in the human’s inbox.
- A human accepts it, signs in as the member and creates the API key. Keep it as
ITSAPLAN_API_KEY.
- Pick the agent’s address. Plus-addressing on a human’s mailbox is the default:
- Claude. Choose how the agent signs in: an API key, a cloud provider, or your own subscription token (within the provider’s terms).
Put each value in a file named after its key in the secrets directory, for example .outstaff/secrets/sam/SLACK_BOT_TOKEN. Keep the environment-variable route (.env) for platforms that can only inject variables; anything in the environment is visible to the agent’s shell.
Let it fill in the rest
Section titled “Let it fill in the rest”ost setup sam --derive--derive reads what you provided (files in the secrets directory first, then the environment) and looks up the values that can be computed:
| Adapter | Needs | Derives |
|---|---|---|
| GitHub | GH_APP_ID and the private key |
GH_APP_SLUG, GH_APP_INSTALLATION_ID (the installation on the team’s repository owner), GH_APP_BOT_EMAIL; the same for the office App |
| Slack | SLACK_BOT_TOKEN |
SLACK_BOT_USER_ID (from auth.test) |
| Its a Plan | ITSAPLAN_API_KEY |
ITSAPLAN_MEMBER_ID (from /me) |
Derived values are written only as files into the secrets directory (.outstaff/secrets/sam/; --secrets-dir and then OUTSTAFF_SECRETS_DIR override it with one folder holding that scope’s files) with mode 0600, and only when the key is not there yet. The command prints key names and warnings, never a value, so its output is safe to paste into a support thread. A warning such as “not installed yet” tells you what to fix before running it again.
GitHub offers the private key as a download. If you set GH_APP_SLUG (the name in the App’s URL) first, --derive finds the newest <slug>.*.pem in ~/Downloads, asks before moving it into the secrets directory as GH_APP_PRIVATE_KEY, and deletes the download. Pass --yes to skip the question in scripts.
Then it has each adapter make what the team needs in its provider and is missing there, and prints a made line for each. The Its a Plan tracker creates the two number fields that show agent tokens and cost on tickets, “Agent tokens” and “Agent cost, USD (API-equivalent)” (Tokens and cost per ticket), unless usage.tracker_fields is off. Creating them needs a key that may create custom fields; when the key may not, the warning says so, and a project admin adds them as number fields in the project’s settings instead.
The office
Section titled “The office”ost setup officeost setup office --deriveThe office has its own template at .outstaff/office/.env.example: the read-only GitHub App that covers every team repository (its printed permissions include Actions: read, so the office can hand an agent the log of a check that failed after a merge), the tracker member the office acts as, and one OUTSTAFF_AGENT_TOKEN_<HANDLE> per person. Generate each token yourself (openssl rand -hex 32) and give the same value to that agent as OUTSTAFF_AGENT_TOKEN. Slack and the model credentials belong to agents and are not listed.
Run ost validate, then ost doctor to check the secrets against GitHub, Slack and the tracker. Give each container its secrets by whatever means you host with (container contract), and start them. Every option of the command is in the CLI reference.