Guide: Linear + Slack¶
This guide walks you through connecting Osmia to a Linear workspace and a Slack workspace so that:
- Issues labelled osmia and in the configured state are automatically picked up by the agent
- The issue receives an
in-progresslabel when work begins - You receive a Slack message when work starts, completes, or fails
Prerequisites¶
| Requirement | Notes |
|---|---|
| Kubernetes cluster | Set one up first if you don't have one |
kubectl configured |
Pointing at the target cluster and namespace |
helm 3+ |
For deploying Osmia |
| Linear workspace | With admin access to create API keys and labels |
| Anthropic API key | For the Claude Code engine |
Step 1 — Create a Linear API key¶
- In Linear, go to Settings → API → Personal API keys.
- Click Create key, name it
osmia, and copy the value.
Service accounts
For production use, create a dedicated Linear member for Osmia and generate the API key under that account, so activity is clearly attributed and the key can be revoked independently.
Step 2 — Find your team ID¶
Osmia needs the Linear team UUID (not the team name) to scope its queries.
curl -s -H "Authorization: YOUR_LINEAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "{ teams { nodes { id name } } }"}' \
https://api.linear.app/graphql | jq '.data.teams.nodes'
Output looks like:
Copy the id value — you will need it for the config.
Step 3 — Create the required labels¶
Osmia uses two labels to track issue state:
- In Linear, go to Settings → Labels.
- Create a label named
osmia— this is the trigger label you add to issues you want the agent to pick up. - Create a label named
osmia-failed— Osmia adds this when a task fails so the issue is not retried automatically.
The in-progress label is typically already present in Linear. If not, create it too.
Step 4 — Create a Slack bot¶
- Go to api.slack.com/apps and click Create New App → From scratch.
- Name it
Osmiaand select your workspace. - Under OAuth & Permissions → Bot Token Scopes, add:
chat:write. - Click Install to Workspace and copy the Bot User OAuth Token (starts with
xoxb-). - In the Slack sidebar, right-click the target channel and copy the Channel ID from the channel details panel.
- Invite the bot to the channel:
/invite @Osmia.
Step 5 — Store credentials as Kubernetes secrets¶
# Linear API key
kubectl create secret generic osmia-linear-token \
--namespace osmia \
--from-literal=token=YOUR_LINEAR_API_KEY
# Anthropic API key (for Claude Code)
kubectl create secret generic osmia-anthropic-key \
--namespace osmia \
--from-literal=api_key=sk-ant-YOUR_KEY_HERE
# Slack bot token
kubectl create secret generic osmia-slack-token \
--namespace osmia \
--from-literal=token=xoxb-YOUR_SLACK_TOKEN_HERE
Step 6 — Write osmia-config.yaml¶
ticketing:
backend: linear
config:
token_secret: osmia-linear-token
team_id: "a1b2c3d4-..." # team UUID from Step 2
state_filter: "Todo" # only pick up issues in this state
labels:
- "osmia" # issues must have this label
exclude_labels:
- "in-progress" # skip issues already being worked on
- "osmia-failed" # skip issues that previously failed
notifications:
channels:
- backend: slack
config:
channel_id: "C0XXXXXXXXX" # channel ID from Step 4
token_secret: osmia-slack-token
engines:
default: claude-code
claude-code:
auth:
method: api_key
api_key_secret: osmia-anthropic-key
execution:
backend: kubernetes
guardrails:
max_cost_per_job: 5.00
max_job_duration_minutes: 60
State filter
Set state_filter to the exact name of the Linear workflow state you want Osmia to poll (e.g. "Todo", "Backlog", "Ready"). Issues in any other state are ignored even if they have the osmia label.
Step 7 — Deploy with Helm¶
helm repo add osmia https://unitaryai.github.io/Osmia
helm repo update
kubectl create namespace osmia
helm install osmia osmia/osmia \
--namespace osmia \
--set-file config=osmia-config.yaml
Verify the controller started cleanly:
You should see:
{"level":"INFO","msg":"linear ticketing backend initialised"}
{"level":"INFO","msg":"slack notification channel initialised"}
{"level":"INFO","msg":"controller initialised and ready"}
Step 8 — Create your first issue¶
-
In Linear, create an issue in your team with a specific, well-scoped task:
Title: Add input validation to the POST /api/users endpoint
Description: The handler does not validate the
emailfield. Reject requests with a missing or malformed email with a 400 and a descriptive error message. Include unit tests. -
Add the osmia label to the issue.
- Ensure the issue is in the
state_filterstate you configured (e.g."Todo").
Within 30 seconds (the default poll interval) the controller will pick it up:
- The
in-progresslabel is added to the issue - A Slack message confirms the agent has started work
- When complete, a comment is posted on the issue with a link to the pull request
Troubleshooting¶
Issues are not being picked up.
- Confirm the label name exactly matches what you configured in
labels. - Confirm the issue is in the workflow state named in
state_filter. - Check
exclude_labels— if the issue hasin-progressorosmia-failedit will be skipped. - Run
kubectl logs -n osmia -l app=osmia --tail=50and look for polling errors.
Authentication errors.
- Verify the secret name matches what you created in Step 5.
- Test the API key directly: You should see your user details returned.
No Slack message received.
- Confirm the bot is invited to the channel (
/invite @Osmia). - Verify the channel ID is correct — it looks like
C0XXXXXXXXX, not the channel name. - Check logs for
"failed to send slack notification".
Next Steps¶
- Configuration Reference — all available config options
- Kubernetes Quick Start — full Helm deployment walkthrough
- Guard Rails Overview — safety limits explained
- Shortcut + Slack guide — if you use Shortcut instead of Linear
- GitHub Issues + Slack guide — if you use GitHub Issues instead of Linear