backflow

module
v0.0.0-...-557f3cc Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 10, 2026 License: MIT

README

Backflow

Agent orchestrator that runs coding agents (Claude Code or Codex) in ephemeral containers. POST a task (repo + prompt), get back a branch with commits and a PR. Three modes: EC2 spot instances, local Docker, or ECS Fargate.

Also supports a read task mode that runs a dedicated reader image against a URL, summarizes it, embeds the TL;DR, and stores the result in a readings table for similarity search. See CLAUDE.md and docs/supabase-setup.md.

Prerequisites

  • Go 1.25+
  • Docker
  • PostgreSQL (or Supabase)
  • jq (for helper scripts)
  • AWS CLI (for EC2/Fargate modes)

Local Development

cp .env.example .env
# Edit .env — at minimum set BACKFLOW_DATABASE_URL, ANTHROPIC_API_KEY, and GITHUB_TOKEN
# Set BACKFLOW_MODE=local for local Docker (no AWS needed)
make build          # Compile to bin/backflow
make run            # Build + run (auto-sources .env, refreshes AWS creds if needed)
make test           # Run all tests (no cache)
make lint           # go vet
make tunnel         # Start cloudflared tunnel → $BACKFLOW_DOMAIN → localhost:8080
make deps           # go mod tidy
make clean          # Remove bin/

Single test: go test ./internal/store/ -run TestCreateTask -v

Tests use testcontainers to spin up ephemeral PostgreSQL instances — Docker must be running.

make test-blackbox      # End-to-end: builds fake agent, starts server + DB, runs happy-path
make test-soak          # Resource leak detector (10 min; truncates tasks DB with confirmation)
make test-fake-agent    # Unit tests for the fake agent image
make test-schema        # Schemathesis fuzz tests against OpenAPI spec
Local Tunnel (for webhooks)

To receive inbound webhooks (Discord interactions, Twilio SMS) during local development, expose your server with a cloudflared named tunnel:

brew install cloudflared
# Set BACKFLOW_TUNNEL_NAME and BACKFLOW_DOMAIN in .env
make cloudflared-setup   # One-time: create tunnel, DNS route, and config
make tunnel              # Start the tunnel

This routes https://$BACKFLOW_DOMAIN to localhost:8080. Set the domain as the Discord Interactions Endpoint URL and Twilio webhook URL. Discord task lifecycle notifications will then land in the configured channel and per-task thread. See docs/discord-setup.md and docs/sms-setup.md for full configuration.

Submitting Tasks

Scripts pass through only explicitly-set options; the server applies defaults for anything omitted. Use --pr / --no-pr to override the server's BACKFLOW_DEFAULT_CREATE_PR setting.

# Simple task (creates PR by default)
./scripts/create-task.sh https://github.com/org/repo "Fix the login bug"

# Skip PR creation
./scripts/create-task.sh https://github.com/org/repo "Fix the login bug" --no-pr

# With options
./scripts/create-task.sh https://github.com/org/repo "Add unit tests" \
  --pr-title "Add tests" --budget 15 --model claude-sonnet-4-6 \
  --branch my-feature --target-branch develop \
  --context "Focus on the auth module" \
  --claude-md "Always use table-driven tests" \
  --effort medium --self-review

# Prompt from a file
./scripts/create-task.sh https://github.com/org/repo --plan plan.md

# With env vars
./scripts/create-task.sh https://github.com/org/repo "Fix bug" \
  --env "GOPRIVATE=github.com/org/*"
PR Reviews
./scripts/review-pr.sh https://github.com/org/repo/pull/42
./scripts/review-pr.sh https://github.com/org/repo/pull/42 --prompt "Focus on security issues"
./scripts/review-pr.sh https://github.com/org/repo/pull/42 --harness codex --budget 5
Direct API
# Create a coding task (server applies defaults for create_pr, effort, etc.)
curl -X POST http://localhost:8080/api/v1/tasks \
  -H "Content-Type: application/json" \
  -d '{
    "repo_url": "https://github.com/org/repo",
    "prompt": "Fix the bug"
  }'

# Review a PR (auto-detects review mode from PR URL in prompt)
curl -X POST http://localhost:8080/api/v1/tasks \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Review https://github.com/org/repo/pull/42"
  }'

# Explicit review mode
curl -X POST http://localhost:8080/api/v1/tasks \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Review https://github.com/org/repo/pull/42"
  }'

# Codex harness (requires OPENAI_API_KEY)
curl -X POST http://localhost:8080/api/v1/tasks \
  -H "Content-Type: application/json" \
  -d '{
    "repo_url": "https://github.com/org/repo",
    "prompt": "Fix the bug",
    "harness": "codex"
  }'

API Reference

Method Path Description
POST /api/v1/tasks Create a task
GET /api/v1/tasks List tasks (?status=, ?limit=, ?offset=)
GET /api/v1/tasks/{id} Get task details
DELETE /api/v1/tasks/{id} Cancel a task
POST /api/v1/tasks/{id}/retry Retry a failed/cancelled/interrupted task
GET /api/v1/tasks/{id}/logs Container logs (?tail=100)
GET /api/v1/health Health check
GET /debug/stats Operational stats (PID, uptime, running tasks, pool metrics)
POST /webhooks/discord Discord interaction endpoint (signature-verified)
POST /webhooks/sms/inbound Twilio inbound SMS webhook
Task Request Fields
Field Type Description
repo_url string Required. Repository URL
prompt string Required for code mode. Agent instructions
task_mode string code, review, or read; auto-detected from PR URLs in prompt when unset
harness string codex or claude_code
model string Model override (per-harness; see server config)
effort string low, medium, high, or xhigh
branch string Working branch name
target_branch string Target branch
create_pr bool Create a PR on completion (omit to use server default)
self_review bool Agent self-reviews the PR after creation (omit to use server default)
pr_title string Custom PR title
pr_body string Custom PR body
max_budget_usd float Budget cap in USD
max_runtime_sec int Runtime cap in seconds
max_turns int Max conversation turns
context string Additional context appended to prompt
claude_md string Extra CLAUDE.md content injected into the repo
allowed_tools []string Restrict agent tool access
env_vars map Extra env vars passed to the container (keys must be POSIX-valid; system keys like ANTHROPIC_API_KEY are reserved)
save_agent_output bool Save agent output to S3 (omit to use server default)

Monitoring and Operations

# Tasks by status
make db-running
make db-pending
make db-completed
make db-failed

# Task details
curl -s http://localhost:8080/api/v1/tasks/{id} | jq .

# Container logs
curl -s 'http://localhost:8080/api/v1/tasks/{id}/logs?tail=100'

# Health check
curl -s http://localhost:8080/api/v1/health

# Operational stats (PID, uptime, running tasks, pool metrics)
curl -s http://localhost:8080/debug/stats | jq .

# Shell into an agent EC2 instance
aws ssm start-session --target i-0abc...
Task Lifecycle

pending -> provisioning -> running -> completed | failed | interrupted | cancelled

Interrupted/failed tasks can enter recovering -> re-queued as pending.

Database

PostgreSQL (hosted on Supabase, connected via session pooler). Migrations managed by goose in migrations/. Auto-runs on startup. Configured via BACKFLOW_DATABASE_URL.

make db-running                             # Show running tasks
make db-pending                             # Show pending tasks
make db-completed                           # Show completed tasks
make db-failed                              # Show failed tasks
psql "$BACKFLOW_DATABASE_URL" -c "\dt"      # List tables
psql "$BACKFLOW_DATABASE_URL" -c "SELECT id, status, created_at FROM tasks ORDER BY created_at DESC LIMIT 10;"

To add a migration: create a new file in migrations/ (e.g. 002_add_column.sql) with -- +goose Up and -- +goose Down sections.

Deployment

Agent Image
make docker-agent-build-local    # Single-arch local build
make docker-agent-deploy         # Multi-arch build + push to ECR
AWS Setup (EC2 Mode)
make setup-aws
# Creates: ECR repo, IAM role, security group, launch template
# Copy BACKFLOW_LAUNCH_TEMPLATE_ID from output into .env
Fargate Mode

Set BACKFLOW_MODE=fargate. No EC2 instances to manage.

# Required in .env
BACKFLOW_MODE=fargate
BACKFLOW_ECS_CLUSTER=backflow
BACKFLOW_ECS_TASK_DEFINITION=backflow-agent
BACKFLOW_ECS_SUBNETS=subnet-abc123,subnet-def456
BACKFLOW_CLOUDWATCH_LOG_GROUP=/ecs/backflow

Prerequisites: ECS cluster with Fargate capacity providers, task definition with awslogs log driver, subnets with egress, IAM roles for image pull + log delivery.

Code Review Agents

This project includes Claude Code agent definitions (.claude/agents/) for automated code review.

Full team review
claude --agent review-lead

Spawns a coordinated team of 4 specialized reviewers (structure, errors, style, security) that examine all non-test Go files and produce a prioritized cleanup report.

Individual reviewers

Run a single reviewer for a focused analysis:

claude --agent structure-reviewer   # Architecture, duplication, dead code
claude --agent error-reviewer       # Error handling, resource management
claude --agent style-reviewer       # Go idioms, naming, simplification
claude --agent security-reviewer    # Injection, auth, secrets, input validation

All agents are read-only — they suggest changes but never modify files. Test files are excluded from review.

Feature Acceptance Agents

A separate agent team evaluates features from a product perspective — not code quality, but whether a feature is complete, safe, maintainable, and documented. All reviewers evaluate against docs/ROADMAP.md as the north star for product direction.

Review a PR
claude --agent acceptance-lead "Review PR #42"
Review an existing feature
claude --agent acceptance-lead "Review the discord feature"
claude --agent acceptance-lead "Review the fargate feature"
claude --agent acceptance-lead "Review the notifications feature"

The lead spawns 5 specialist reviewers in parallel:

Reviewer Focus
product-reviewer Roadmap alignment, persona fit, competitive positioning, cross-mode completeness
acceptance-security-reviewer Attack surface, auth boundaries, credential handling, threat model
quality-reviewer Test coverage, edge cases, status transitions, graceful degradation
maintainability-reviewer Pattern consistency, config model, observability, complexity budget
documentation-reviewer CLAUDE.md accuracy, config docs, schema docs, discoverability

The consolidated report ends with a verdict: ACCEPT, ACCEPT WITH CONDITIONS, or REQUEST CHANGES.

All agents are read-only — they analyze and report but never modify files or post PR comments.

Configuration

All config via environment variables or .env file. See .env.example for the full list.

General
Variable Default Description
BACKFLOW_MODE ec2 ec2, local, or fargate
ANTHROPIC_API_KEY Required
OPENAI_API_KEY Required for codex harness; also required for reading-mode completion (embedding the TL;DR)
GITHUB_TOKEN For cloning private repos and creating PRs
BACKFLOW_LISTEN_ADDR :8080 Server listen address
BACKFLOW_DATABASE_URL PostgreSQL connection string (Supabase session pooler recommended)
BACKFLOW_POLL_INTERVAL_SEC 5 Orchestrator poll interval (seconds)
BACKFLOW_S3_BUCKET S3 bucket for agent output and large prompt offload
Reading Mode
Variable Description
BACKFLOW_READER_IMAGE Docker image used for task_mode=read containers
BACKFLOW_DEFAULT_READ_MAX_BUDGET Budget cap for reading tasks
BACKFLOW_DEFAULT_READ_MAX_RUNTIME_SEC Runtime cap for reading tasks
BACKFLOW_DEFAULT_READ_MAX_TURNS Max turns for reading tasks
SUPABASE_URL Supabase project URL passed to reader containers
SUPABASE_ANON_KEY Supabase publishable key (sb_publishable_...) passed to reader containers for PostgREST calls

See docs/supabase-setup.md for the readings schema, reader PostgREST schema, and key model.

Agent Defaults

Defaults are set in internal/config/config.go and can be overridden via env vars. See .env.example for current values.

Variable Description
BACKFLOW_DEFAULT_HARNESS claude_code or codex
BACKFLOW_DEFAULT_CLAUDE_MODEL Default model for Claude Code
BACKFLOW_DEFAULT_CODEX_MODEL Default model for Codex
BACKFLOW_DEFAULT_EFFORT Reasoning effort (low, medium, high, xhigh)
BACKFLOW_DEFAULT_MAX_BUDGET Budget cap (USD)
BACKFLOW_DEFAULT_MAX_RUNTIME_SEC Runtime cap (seconds)
BACKFLOW_DEFAULT_MAX_TURNS Max conversation turns
BACKFLOW_DEFAULT_CREATE_PR Create PR by default
BACKFLOW_DEFAULT_SELF_REVIEW Self-review by default
BACKFLOW_DEFAULT_SAVE_AGENT_OUTPUT Save agent output by default
BACKFLOW_AGENT_IMAGE Docker image for agent containers (see config for default)
BACKFLOW_MAX_USER_RETRIES Max user-initiated retries per task (see config for default)
BACKFLOW_CONTAINER_CPUS CPU cores per container
BACKFLOW_CONTAINER_MEMORY_GB Memory (GB) per container
EC2 Mode
Variable Default Description
AWS_REGION us-east-1 AWS region
BACKFLOW_INSTANCE_TYPE m7g.xlarge EC2 instance type
BACKFLOW_LAUNCH_TEMPLATE_ID From make setup-aws
BACKFLOW_MAX_INSTANCES 5 Max EC2 instances
BACKFLOW_CONTAINERS_PER_INSTANCE 1 Containers per instance
Fargate Mode
Variable Default Description
BACKFLOW_ECS_CLUSTER ECS cluster name (required)
BACKFLOW_ECS_TASK_DEFINITION Task definition ARN or family (required)
BACKFLOW_ECS_SUBNETS Comma-separated subnet IDs (required)
BACKFLOW_CLOUDWATCH_LOG_GROUP CloudWatch log group (required)
BACKFLOW_ECS_SECURITY_GROUPS Comma-separated security group IDs
BACKFLOW_ECS_LAUNCH_TYPE FARGATE_SPOT FARGATE or FARGATE_SPOT
BACKFLOW_ECS_CONTAINER_NAME backflow-agent Container name in task definition
BACKFLOW_ECS_LOG_STREAM_PREFIX ecs CloudWatch log stream prefix
BACKFLOW_ECS_ASSIGN_PUBLIC_IP true false for private subnets with NAT
BACKFLOW_MAX_CONCURRENT_TASKS 5 Max concurrent Fargate tasks
Webhooks
Variable Default Description
BACKFLOW_WEBHOOK_URL Webhook endpoint URL
BACKFLOW_WEBHOOK_EVENTS all Comma-separated event filter

Events: task.created, task.running, task.completed, task.failed, task.needs_input, task.interrupted, task.recovering, task.cancelled, task.retry

Discord
Variable Default Description
BACKFLOW_DISCORD_APP_ID Discord application ID (enables integration when set)
BACKFLOW_DISCORD_PUBLIC_KEY Ed25519 public key for interaction verification
BACKFLOW_DISCORD_BOT_TOKEN Bot token for API calls
BACKFLOW_DISCORD_GUILD_ID Target server ID
BACKFLOW_DISCORD_CHANNEL_ID Target channel ID
BACKFLOW_DISCORD_ALLOWED_ROLES Comma-separated role IDs for mutation authorization
BACKFLOW_DISCORD_EVENTS all Comma-separated event filter

See docs/discord-setup.md for full setup instructions.

SMS (Twilio)
Variable Default Description
BACKFLOW_SMS_PROVIDER Set to twilio to enable SMS
TWILIO_ACCOUNT_SID Twilio Account SID (required when provider is twilio)
TWILIO_AUTH_TOKEN Twilio Auth Token (required when provider is twilio)
BACKFLOW_SMS_FROM_NUMBER Twilio phone number in E.164 format (required when provider is twilio)
BACKFLOW_SMS_EVENTS task.completed,task.failed Comma-separated events that trigger outbound SMS
BACKFLOW_SMS_OUTBOUND_ENABLED true Set to false to disable outbound SMS while keeping inbound

See docs/sms-setup.md for full setup instructions including allowed sender registration and A2P 10DLC compliance.

Directories

Path Synopsis
cmd
backflow command
internal
api
embeddings
Package embeddings provides a minimal client for text embedding APIs.
Package embeddings provides a minimal client for text embedding APIs.
test
soak command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL