Skip to main content

Takopi transport backend for Linear Agent SDK

Project description

takopi-linear

Linear transport backend plugin for takopi. Turns Linear into a full project management interface for your AI coding agent — delegate issues, track progress through native Agent Activities, and get PRs back.

Status: pre-alpha / early development. Not recommended for production use yet.

How it works

┌─────────────┐     webhook      ┌──────────────────┐     Neon DB      ┌─────────────────┐
│   Linear    │ ──────────────►  │   kai-gateway    │ ──────────────►  │  takopi-linear  │
│  (issues,   │                  │   (Vercel)       │    events table  │  (this plugin)  │
│  comments,  │  ◄────────────── │                  │                  │                 │
│  agent UI)  │   GraphQL API    └──────────────────┘  ◄────────────── │  polls for new  │
└─────────────┘                                          poll + claim  │  events, runs   │
                                                                       │  takopi engine   │
                                                                       └─────────────────┘
  1. A user creates a Linear issue and delegates it to the bot (assigns as agent)
  2. Linear fires an AgentSessionEvent webhook to kai-gateway
  3. kai-gateway validates the signature, normalizes the event, and inserts it into a shared Neon (Postgres) database
  4. takopi-linear polls the database, claims the event, and starts a takopi session
  5. The AI engine (Claude Code, Codex, etc.) does the work — progress streams back to Linear as native Agent Activities (thoughts, plans, actions)
  6. When done, the bot creates a PR, transitions the issue to Done, and posts a final response

Setup guide

Prerequisites

  • Python 3.14+
  • A Neon Postgres database (free tier works)
  • A Vercel account (for deploying kai-gateway)
  • A Linear workspace with admin access
  • takopi installed and configured with at least one engine backend

Step 1: Create the Neon database

  1. Sign up at neon.tech and create a new project
  2. Create a database called kai_gateway
  3. Run the schema to create the events table:
CREATE EXTENSION IF NOT EXISTS pgcrypto;

CREATE TABLE events (
    id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    source      TEXT NOT NULL,
    event_type  TEXT NOT NULL,
    external_id TEXT,
    payload     JSONB NOT NULL,
    status      TEXT NOT NULL DEFAULT 'pending',
    created_at  TIMESTAMPTZ NOT NULL DEFAULT now(),
    processed_at TIMESTAMPTZ,
    error       TEXT
);

CREATE INDEX idx_events_status ON events (status) WHERE status = 'pending';
CREATE INDEX idx_events_source ON events (source, status);
CREATE UNIQUE INDEX idx_events_external_id ON events (source, external_id) WHERE external_id IS NOT NULL;
  1. Copy your connection string — you'll need it for both kai-gateway and takopi-linear:
    postgresql://user:pass@host.neon.tech/kai_gateway?sslmode=require
    

Step 2: Deploy kai-gateway

kai-gateway is a lightweight Vercel serverless function that receives Linear webhooks and writes them to the shared Neon database.

  1. Clone the repo:

    git clone https://github.com/asianviking/kai-gateway.git
    cd kai-gateway
    
  2. Deploy to Vercel:

    npx vercel
    
  3. Set the environment variables in Vercel (Settings > Environment Variables):

    Variable Description
    DATABASE_URL Neon connection string from Step 1
    LINEAR_WEBHOOK_SECRET You'll get this from Linear in Step 3
  4. Note your deployment URL (e.g. https://kai-gateway.vercel.app) — you'll need it when configuring the Linear webhook.

Step 3: Create the Linear bot application

  1. Go to Linear Settings > API > Applications and create a new application
  2. Configure the application:
    • Name: Your bot's name (e.g. "Kai")
    • Actor: Select Application (this gives the bot its own identity)
    • OAuth scopes: Enable app:assignable, app:mentionable, read, write
  3. Install the application to your workspace (requires admin)
  4. Copy the OAuth access token and Application ID — you'll need these for takopi-linear config
  5. Set up the webhook:
    • Webhook URL: https://your-kai-gateway.vercel.app/webhooks/linear
    • Signing secret: Generate one and save it — add this to kai-gateway's LINEAR_WEBHOOK_SECRET env var
    • Events: Enable Issues, Comments, and Agent sessions

Step 4: Install and configure takopi-linear

  1. Install the plugin:

    pip install takopi-linear
    
  2. Add the Linear transport to your takopi.toml:

    transport = "linear"
    
    [transports.linear]
    oauth_token = "lin_oauth_..."       # from Step 3
    app_id = "your-app-id"              # from Step 3
    gateway_database_url = "postgresql://...@...neon.tech/kai_gateway?sslmode=require"  # from Step 1
    poll_interval = 5.0
    
    # Map Linear projects to local repos
    [plugins.linear]
    project_map = { "linear-project-uuid" = "my-project" }
    
  3. Start takopi — it will begin polling the gateway database for new events:

    takopi run
    

Step 5: Test the integration

  1. Create a new Linear issue in a mapped project
  2. Assign the bot as the agent (delegate to it)
  3. The bot should acknowledge within a few seconds with an initial plan
  4. Watch it work through the issue and deliver a PR

Configuration reference

Transport settings ([transports.linear])

[transports.linear]
# Required
oauth_token = "..."                          # Linear OAuth access token (actor=app)
app_id = "..."                               # Linear application ID
gateway_database_url = "postgresql://..."     # Neon DB connection string

# Polling
poll_interval = 5.0                          # seconds between polls (default: 5.0)
poll_batch_size = 10                         # events per poll (default: 10)

# Message formatting
message_overflow = "split"                   # "split" or "trim" (default: "split")
max_body_chars = 10000                       # split threshold (default: 10000)
plan_coalesce_s = 1.0                        # debounce plan updates (default: 1.0)
ephemeral_activity_coalesce_s = 0.2          # debounce thought updates (default: 0.2)

# Attachments
download_attachments = true                  # download attached files from prompts
attachment_allowed_hosts = ["uploads.linear.app"]
attachment_max_bytes = 20000000              # 20 MB
attachment_dir = ".takopi-linear/attachments"

Direct webhook server (optional)

For lower latency, you can also run a direct webhook server alongside DB polling. Events are deduplicated across both paths.

[transports.linear]
webhook_enabled = true
webhook_host = "0.0.0.0"
webhook_port = 8080
webhook_path = "/webhooks/linear"
webhook_signing_secret = "..."               # HMAC-SHA256 signing secret

Plugin settings ([plugins.linear])

[plugins.linear]
# Project mapping (required — maps Linear project IDs to takopi project aliases)
project_map = { "linear-project-id" = "backend" }

# Worktrees
worktree_strategy = "per_issue"              # "per_issue" (default) or "shared"
branch_prefix = "kai/"                       # branch prefix (default: "kai/")

# Workflow transitions (optional)
success_state_name = "In Review"             # case-insensitive; falls back to first type="completed"
# success_state_names = ["Ready for Review", "In Review"]  # first match wins

# Auto-labels (opt-in)
auto_labels_enabled = false
auto_labels = { processed = "agent:processed", completed = "agent:completed", failed = "agent:failed" }

# Sub-issues (opt-in — create sub-issues from checklist items)
subissues_enabled = false
subissues_max = 5

# Comment follow-ups (treat new comments as continuation prompts)
comment_followups_enabled = true
comment_followups_debounce_seconds = 0.5

# Prioritization
event_prioritization_enabled = true          # sort by issue priority + cycle
current_cycle_only = false                   # skip issues outside current cycle

# Metadata
estimate_updates_enabled = false             # update issue estimates

# Engine/model overrides per project
project_models = { "backend" = "opus" }      # default model per project
project_reasoning = { "backend" = "high" }   # default reasoning level per project
project_engines = { "backend" = "claude" }   # default engine per project

File transfer ([transports.linear.files])

[transports.linear.files]
enabled = true
auto_put = true
auto_put_mode = "prompt"                     # "upload" = save only, "prompt" = save + annotate prompt
uploads_dir = "incoming"

Usage

Delegating work

Create a Linear issue and assign the bot as the agent. The issue title becomes the prompt:

Issue title Branch Prompt
Add JWT authentication kai/AV-123 (auto) "Add JWT authentication"
@feat/auth Add JWT authentication feat/auth (custom) "Add JWT authentication"

Title directives

Override model, reasoning, or engine per issue using brackets in the title:

[model:sonnet] Fix the login bug
[reasoning:high] Refactor the auth module
[engine:codex] Scaffold the new API

Or use Linear labels: model > sonnet, engine > codex, reasoning > high.

Special commands

Use these in issue comments:

Command Effect
stop, cancel Cancel the current run
/new, /reset Clear session context and start fresh
/help, help, ? Show help text
/file put <path> Upload an attached file to the working directory
/file get <path> Download a file (or zipped directory) back to Linear

Worktrees / branching

By default (worktree_strategy = "per_issue"), each issue runs in its own git worktree with a branch derived from the issue identifier (e.g. kai/AV-123).

To override per issue, prefix the title with @branch/name (e.g. @fix/login Fix the login bug).

kai-gateway

kai-gateway is the webhook ingress layer that sits between Linear and takopi-linear. It's a simple Vercel serverless function that:

  1. Receives Linear webhook events at POST /webhooks/linear
  2. Verifies the HMAC-SHA256 signature
  3. Checks for replay attacks (rejects stale deliveries)
  4. Normalizes the event payload
  5. Inserts it into the shared Neon events table with deduplication

takopi-linear then polls this table, atomically claims pending events using FOR UPDATE SKIP LOCKED, and processes them. This decoupled architecture means:

  • No public endpoint needed on the takopi host — it only makes outbound connections
  • Multiple consumers can safely poll the same table (events won't be double-processed)
  • Events are durable — if takopi is down, events queue up and are processed when it comes back

Environment variables (kai-gateway)

Variable Description
DATABASE_URL Neon Postgres connection string
LINEAR_WEBHOOK_SECRET HMAC-SHA256 signing secret (must match Linear app webhook config)

Development

# Clone and install
git clone https://github.com/asianviking/takopi-linear.git
cd takopi-linear
uv sync --extra test

# Run tests
uv run pytest

# Build
uv build

See RELEASING.md for the release process.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

takopi_linear-0.1.0.tar.gz (106.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

takopi_linear-0.1.0-py3-none-any.whl (50.6 kB view details)

Uploaded Python 3

File details

Details for the file takopi_linear-0.1.0.tar.gz.

File metadata

  • Download URL: takopi_linear-0.1.0.tar.gz
  • Upload date:
  • Size: 106.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for takopi_linear-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e4e5a1ab86391414b7331335aa2e8d6ace598668462451d5ef8dd6532ce634e3
MD5 801f21a8f35706ef79b3ef02deaa0f98
BLAKE2b-256 1364d8dae1c55aec504edba0f0fedbf939d2bc921de754910d00e3bd33bb0dee

See more details on using hashes here.

Provenance

The following attestation bundles were made for takopi_linear-0.1.0.tar.gz:

Publisher: release.yml on asianviking/takopi-linear

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file takopi_linear-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: takopi_linear-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 50.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for takopi_linear-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bd39988458adabe198c7c0e5caf0ae0ece62b106ba67c23dc11d38d4f755af9a
MD5 a5df202a1caf9cf7b1294d96b00e6b54
BLAKE2b-256 916b564d8a6786ce9a250489dd8d0ac8572793394a0448b6319afeb9371ce47d

See more details on using hashes here.

Provenance

The following attestation bundles were made for takopi_linear-0.1.0-py3-none-any.whl:

Publisher: release.yml on asianviking/takopi-linear

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page