Skip to content

Automated Workflow — Linear Issue → Pull Request

Architecture Overview

┌──────────┐     ┌──────────┐     ┌────────────────────┐
│  Linear  │────▶│   n8n   │────▶│   Pipeline.py     │
│  Issues  │     │ Webhook │     │ (Docker/Studio)   │
└──────────┘     └──────────┘     └────────────────────┘


                                    ┌────────────────────┐
                                    │ 6-Agent Chain     │
                                    │ PM → Architect → │
                                    │ Coder → Reviewer→ │
                                    │ Healer → Release │
                                    └────────────────────┘


                                    ┌────────────────────┐
                                    │  opencode  │
                                    │ (All Providers)  │
                                    └────────────────────┘

1. Supported LLM Providers (via 9router)

All LLM calls route through 9router (port 20128) for unified API proxy with centralized key management:

opencode (docker exec) → 9router → provider APIs (NVIDIA, MiniMax, DeepSeek, Claude)

How the 6 agents pick LLM providers

The pipeline.py TIER_MODEL maps each agent to a provider. When opencode runs, it uses the model name to route through 9router, which then forwards to the actual provider.

ProviderModel (for opencode)Provider APICost/1M tokens
NVIDIAnvidia/meta/llama-3.1-70b-instructNVIDIA NIM~$0.40
MiniMaxminimax-coding-plan/MiniMax-M2.7MiniMax API~$0.30
DeepSeekdeepseek/deepseek-chatDeepSeek API~$0.14
OpenAIgithub-copilot/gpt-4oOpenAI API~$2.50
Claudegithub-copilot/claude-sonnet-4.5Anthropic API~$3.00

opencode auth.json configuration

opencode container uses *_api_base keys to route all calls through 9router:

json
{
  "nvidia": {"type": "api", "key": "${NVIDIA_API_KEY}"},
  "minimax-coding-plan": {"type": "api", "key": "${MINIMAX_API_KEY}"},
  "deepseek": {"type": "api", "key": "${DEEPSEEK_API_KEY}"},
  "claude-premium": {"type": "api", "key": "${CLAUDE_API_KEY}"},
  "minimax_api_base": "http://devstation-studio-9router-1:20128/v1"
}

Fallback Chain (within 9router)

When a provider fails, 9router handles failover:

PrimaryFalls back to
nvidiaminimax → deepseek → error
minimaxnvidia → deepseek → error
deepseeknvidia → minimax → error
claude-premiumnvidia → minimax → error

Tier routing (pipeline.py TIER_MODEL)

| Tier | PM | Architect | Coder | Reviewer | Healer | |---|---|---|---|---|---|---| | Simple | nvidia | nvidia | nvidia | nvidia | nvidia | | Medium | nvidia | nvidia | nvidia | nvidia | nvidia | | Complex | nvidia | nvidia | nvidia | nvidia | nvidia | | Premium | claude-premium | claude-premium | claude-premium | claude-premium | claude-premium |

Cost estimate (monthly, 60 tasks)

TierTasksProviderCost/taskMonthly
Simple24NVIDIA~$0.01~$0.24
Medium24NVIDIA~$0.02~$0.48
Complex12NVIDIA~$0.05~$0.60
Premium~5Claude~$0.30~$1.50
Total~65~$2.82

Claude Premium only activates when you tag an issue with premium or claude.


2. Hybrid Devin-Station Workflow (NHA-21)

For complex tasks, you can use Devin for architectural planning and the Local Station for implementation.

  1. Plan Phase (Devin):
    • Add the !plan label to a Linear issue.
    • Devin analyzes the task and posts a plan as a comment and in docs/plans/.
  2. Implement Phase (Local):
    • Add the implement label to the Linear issue.
    • Local pipeline reads Devin's plan and executes the Coder/Reviewer/Healer chain.

3. Tag-Based Two-Phase Trigger

Linear Issue created/updated with tag "plan" or "implement"
  → n8n webhook → POST /webhook to pipeline.py (Mac Studio)
  → projects.yaml lookup (team_id → repo, base_branch, trigger_labels)
  → complexity gate → Execute phase based on tag

2. Phase: Plan (tag: "plan")

3. Phase: Implement (tag: "implement")

4. 6-Agent Chain

AgentRoleInputOutputDefault Provider
PMSpec generationIssue title + bodyJSON: spec, acceptance_criteria, files, riskOllama (simple) / DeepSeek (medium+)
ArchitectTechnical planningSpec + plan.mdJSON: file_plan, invariants, test_planOllama / DeepSeek / o3-mini / Claude
CoderCode generationPlanJSON: file contents + commandsOllama / DeepSeek / o3-mini / Claude
ReviewerCode reviewGit diffJSON: overall, issues, summaryOllama / DeepSeek / o3-mini / Claude
HealerAuto-fixDiff + review issuesJSON: fixed filesOllama / DeepSeek
ReleasePR managementBranch, title, bodyPR URLOllama / DeepSeek

5. Multi-Repo Configuration

Edit projects.yaml to map Linear teams to GitHub repos:

yaml
projects:
  healthtech:
    linear_team_id: "TEAM_UUID_1"
    github_repo: "org/healthtech"
    trigger_labels:
      plan: "plan"
      implement: "implement"

6. Cost Control

Branch Naming Convention

All Git branches use the format feat/<issue-id>-<title-slug>:

  • Example: feat/AI-123-fix-login-oauth
  • Slug is max 30 characters, lowercase, spaces replaced with dashes
  • Slug is generated from the issue title using slugify() function in pipeline.py
python
def slugify(text: str, max_len: int = 40) -> str:
    text = text.lower()
    text = re.sub(r'[^a-z0-9]+', '-', text)
    text = re.sub(r'^-|-$', '', text)
    return text[:max_len]

This makes branches human-readable while remaining valid Git branch names.

TierCloud Cost/TaskMonthly (60 tasks)
Simple (24 tasks)$0$0
Medium (24 tasks)~$0.01~$0.24
Complex (12 tasks)~$0.08~$0.96
Classification overhead~$0.001~$0.06
Total~$1.26

Claude Premium only activates when you tag an issue with premium or claude. At ~$0.30/task, using it for 5 tasks/month adds ~$1.50 — still well under $20.

7. Error Handling

FailureRetryEscalation
LLM timeoutTier-aware fallback chainTelegram notify
Review blockedStop, notify human
Review changes_requestedHealer agent (max 3)Human review via Telegram/PWA
Git push conflictRebase + retryTelegram notify
All providers downGrafana alert + Telegram

MIT Licensed | Built with AI Dev Station