Skip to content

Repository files navigation

Rob Agent Factory

An AI agent factory that processes open GitHub issues through two connected pipelines:

  • Planning Pipeline: Triage -> Spec -> Plan -> Tasks
  • Execution Pipeline: Implement -> Review -> Ship

The factory separates discovery and planning work from implementation work. The planning pipeline runs well as a deployed Cloudflare Worker service. The execution pipeline is local-first and designed to run with real access to git, npm, and gh — now with an optional Docker sandbox for isolated AI execution.


Table of Contents

  1. What It Does
  2. Architecture Overview
  3. End-To-End Flow
  4. Planning Pipeline
  5. Execution Pipeline
  6. Sandboxed Execution (Docker)
  7. Repository Structure
  8. Requirements
  9. Installation
  10. Configuration
  11. Main Commands
  12. Testing Guide
  13. Deployment Guide
  14. GitHub Actions Integration
  15. Managed Labels & Markers
  16. Troubleshooting

What It Does

  • Detects open issues in configured GitHub repositories.
  • Generates structured artifacts per stage.
  • Writes comments and managed sections inside the issue.
  • Adds labels to move the issue between states.
  • Executes implementation in an isolated workspace per issue.
  • Runs baseline checks on the target repository.
  • Creates branch, push, and draft PR when execution reaches Ship.

Architecture Overview

flowchart TB
    subgraph Host["Host Machine"]
        direction TB
        Flue["Flue Agent Orchestrator"]
        GH_CLI["gh CLI"]
        Git["git"]
        NPM["npm"]
    end

    subgraph Cloud["Cloudflare Workers"]
        direction TB
        Worker["Factory Worker<br/>(Planning Pipeline)"]
    end

    subgraph Docker["Docker Sandbox (Optional)"]
        direction TB
        Container["sandcastle:openrouter-agent<br/>Container"]
        Agent["openrouter-agent CLI"]
        OR_API["OpenRouter API"]
    end

    subgraph GitHub["GitHub"]
        direction TB
        Issues["Issues API"]
        PRs["Pull Requests API"]
    end

    Issues --> Worker
    Worker --> Issues
    Worker --> Flue
    Flue --> GH_CLI
    Flue --> Git
    Flue --> NPM
    Flue -. "sandboxed mode" .-> Container
    Container --> Agent
    Agent --> OR_API
    GH_CLI --> PRs
    Git --> PRs
Loading
Component Role
Flue Orchestrates agents and stages
OpenRouter Provides the main LLM (planning + execution)
GitHub REST Universal fallback for reading/writing issues
GitHub MCP Used in planning when available
Cloudflare Workers Hosts the HTTP entrypoint for planning
gh, git, npm Used during local execution
Docker + Sandcastle Optional isolated sandbox for execution

End-To-End Flow

flowchart LR
    A["Open GitHub Issue"] --> B["Workflow: issue-opened.yml"]
    B --> C["Factory on Cloudflare"]
    C --> D["Planning Pipeline"]
    D --> E["Comments + Checklist + Labels"]
    E --> F["Label: factory:ready-for-implementation"]
    F --> G["Workflow: issue-ready-for-implementation.yml"]
    G --> H{"Execution Mode"}
    H -->|local| I["Local Execution"]
    H -->|sandboxed| J["Docker Sandbox Execution"]
    I --> K["Branch + Changes + Verification"]
    J --> K
    K --> L["Draft PR"]
Loading

Planning Pipeline

The planning pipeline processes an issue and publishes incremental artifacts:

  1. triage
  2. spec
  3. plan
  4. tasks

When tasks completes, the factory:

  • Updates the issue with a managed Factory Tasks section
  • Ensures the label factory:ready-for-implementation
  • Leaves the issue ready for the execution pipeline
flowchart TD
    A["Open Issue or Manual Payload"] --> B["Triage"]
    B --> C["Spec"]
    C --> D["Plan"]
    D --> E["Tasks"]
    E --> F["Write Comments by Marker"]
    E --> G["Update Checklist in Issue Body"]
    E --> H["Add Label: factory:ready-for-implementation"]
Loading

Execution Pipeline

The execution pipeline expects an issue with generated tasks and the label factory:ready-for-implementation.

Local Mode

  1. Clones the target repo into .factory-workspaces/.
  2. Creates a branch with configurable prefix.
  3. Runs baseline project checks.
  4. Executes implement.
  5. Executes review.
  6. Executes ship.
  7. Pushes branch and opens draft PR.
flowchart TD
    A["Issue with Tasks + Ready Label"] --> B["Prepare Isolated Workspace"]
    B --> C["Install Target Repo Dependencies"]
    C --> D["Implement"]
    D --> E["Verification"]
    E --> F["Review"]
    F --> G["Ship"]
    G --> H["Commit + Push + Draft PR"]
Loading

Sandboxed Mode (Docker)

In sandboxed mode, the AI agent runs inside a Docker container while git/npm operations remain on the host.

flowchart TB
    subgraph Host["Host Machine"]
        direction TB
        A["Factory Agent"]
        B["git / npm / gh"]
        C["Workspace<br/>.factory-workspaces/"]
    end

    subgraph Sandbox["Docker Sandbox"]
        direction TB
        D["sandcastle:openrouter-agent"]
        E["openrouter-agent CLI"]
        F["OpenRouter API"]
    end

    A -->|"1. clone / checkout"| B
    B --> C
    A -->|"2. prompt + context"| D
    D --> E
    E -->|"3. chat completion"| F
    F -->|"4. tool calls"| E
    E -->|"5. write files"| C
    A -->|"6. verify / commit / push"| B
Loading

Sandboxed Execution (Docker)

Why Sandbox?

The sandboxed execution mode runs the AI coding agent inside an isolated Docker container. This provides:

  • Isolation: The agent cannot accidentally modify files outside the workspace.
  • Reproducibility: Same environment every time, regardless of host machine state.
  • Security: Unknown or experimental code runs in a container, not on your host.

How It Works

sequenceDiagram
    participant Host as Host Factory
    participant Docker as Docker Daemon
    participant Container as sandcastle Container
    participant OR as OpenRouter API

    Host->>Docker: docker build sandcastle:openrouter-agent
    Docker-->>Host: Image ready
    Host->>Docker: docker run (detached)
    Docker->>Container: Start container with tail -f /dev/null
    Host->>Docker: docker exec openrouter-agent --model <model>
    Docker->>Container: Execute agent CLI
    Container->>OR: POST /chat/completions
    OR-->>Container: Response with tool calls
    Container->>Container: Execute Bash/ReadFile/WriteFile
    Container-->>Host: Final JSON output
    Host->>Docker: docker stop & remove
Loading

Sandbox Architecture

flowchart LR
    subgraph HostOps["Host Operations"]
        GitClone["git clone / checkout"]
        NpmInstall["npm install"]
        GitCommit["git commit / push"]
    end

    subgraph SandboxOps["Sandbox Operations (Docker)"]
        AIAgent["AI Agent"]
        FileEdit["File Read / Write"]
        BashCmd["Bash Commands"]
    end

    GitClone --> Workspace["Workspace Directory<br/>(bind-mounted)"]
    Workspace --> FileEdit
    FileEdit --> Workspace
    AIAgent --> BashCmd
    BashCmd --> Workspace
    Workspace --> GitCommit
Loading

Repository Structure

File Description
.flue/agents/factory.ts Main agent and stage orchestration
.flue/lib/config.ts Configuration loader from factory.config.json, .env, and payload
.flue/lib/execution.ts Local execution backend: workspaces, git, and verification
.flue/lib/sandboxed-execution.ts NEW Sandboxed execution backend using Docker + Sandcastle
.flue/lib/execution-common.ts Shared utilities for both execution backends
.flue/lib/sandcastle/openrouter.ts NEW Custom Sandcastle AgentProvider for OpenRouter
.flue/lib/github.ts REST integration with GitHub
scripts/openrouter-agent.mjs NEW CLI agent that runs inside the Docker sandbox
scripts/run-local-test.mjs Local runner for planning and execution
scripts/run-local-http-test.mjs HTTP test against local worker
scripts/run-sandboxed-test.mjs NEW Runner for sandboxed execution
.sandcastle/Dockerfile NEW Docker image for the sandbox
docs/local-testing.md Short guide for local testing

Requirements

  • Node.js 22 (recommended)
  • npm
  • git
  • gh CLI (authenticated if testing full execution pipeline)
  • Docker (only if using sandboxed execution mode)
  • OpenRouter account and API key
  • GitHub token with permissions for issues, contents, and pull-requests
  • Cloudflare access if deploying the worker

Installation

Step 1: Install Dependencies

npm install

Step 2: Create Your Environment File

cp .env.example .env

Step 3: Fill in Required Variables

Edit .env and provide at least:

GITHUB_TOKEN=ghp_xxx
OPENROUTER_API_KEY=sk-or-v1-xxx

Optional but useful variables:

FACTORY_REPOS=owner/repo-one,owner/repo-two
FACTORY_MODEL=openrouter/openai/gpt-5.1
FACTORY_WRITE_BACK=true
FACTORY_MAX_ISSUES_PER_REPO=1
FACTORY_EXECUTION_MODE=local
FACTORY_EXECUTION_ROOT=.factory-workspaces

Step 4: Choose Execution Mode

The factory supports two execution modes. Set FACTORY_EXECUTION_MODE in .env:

Mode Value Description
Local local AI agent runs directly on your host machine (default)
Sandboxed sandboxed AI agent runs inside a Docker container

You can also override per-command:

npm run local:execute -- --repo owner/repo --issue 123 --execution-mode sandboxed

Step 5: Validate Environment

npm run local:validate

This checks:

  • .env exists
  • GITHUB_TOKEN is present
  • OPENROUTER_API_KEY is present
  • Cloudflare build can be generated
  • TypeScript has no errors

Step 6: Build the Sandbox Image (Sandboxed Mode Only)

If you plan to use sandboxed execution, build the Docker image once:

npm run sandbox:build-image

Or let the factory auto-build it on first run.


Configuration

factory.config.json

{
  "repos": [],
  "maxIssuesPerRepo": 3,
  "model": "openrouter/openai/gpt-5.1",
  "writeBack": true,
  "execution": {
    "defaultMode": "local",
    "sandboxed": false,
    "branchPrefix": "factory",
    "workspaceRoot": ".factory-workspaces",
    "prDraft": true
  }
}
Key Description
execution.defaultMode Default execution mode (local or sandboxed)
execution.sandboxed Whether sandboxed mode is enabled in config
execution.branchPrefix Prefix for generated branches
execution.workspaceRoot Directory for isolated workspaces
execution.prDraft Whether to create draft PRs

Main Commands

# Type check and build
npm run check

# Development server (Cloudflare worker)
npm run dev:cloudflare

# Build for Cloudflare deployment
npm run build:cloudflare

# --- Planning Commands ---
npm run local:dry-run -- --repo owner/repo --issue 123 --stage full
npm run local:write-test -- --repo owner/repo --issue 123 --stage full

# --- Execution Commands ---
# Local execution
npm run local:execute -- --repo owner/repo --issue 123 --stage execute

# Sandboxed execution
npm run sandbox:execute -- --repo owner/repo --issue 123

# --- HTTP Testing ---
npm run local:http-test -- --repo owner/repo --issue 123 --stage full

Testing Guide

1. Smoke Test

Confirm the project compiles and minimum credentials exist:

npm run local:validate
npm run check

2. Test Planning Without Writing to GitHub

Use this to validate prompts, payloads, and repo access without modifying the issue:

npm run local:dry-run -- --repo owner/repo --issue 123 --stage full
  • Forces writeBack=false
  • Runs triage, spec, plan, and tasks
  • Safest way to test prompt or configuration changes

3. Test Planning With Real Writes

If you want to verify comments, markers, and labels:

npm run local:write-test -- --repo owner/repo --issue 123 --stage full
  • Uses writeBack=true
  • The issue will be modified

4. Test Local Execution

Requires an issue with a Factory Tasks checklist and the label factory:ready-for-implementation.

npm run local:execute -- --repo owner/repo --issue 123 --stage execute

During this test the factory:

  • Clones the target repo into .factory-workspaces/
  • Creates a branch with format factory/<owner-repo>/issue-<n>
  • Runs npm install
  • Runs npm test (with --runInBand for Jest, without for Vitest)
  • Runs npm run build if available

5. Test Sandboxed Execution

npm run sandbox:execute -- --repo owner/repo --issue 123

What happens:

  1. Builds Docker image sandcastle:openrouter-agent if missing
  2. Clones repo to .factory-workspaces/
  3. Starts Docker container with bind-mounted workspace
  4. Runs openrouter-agent inside container with OpenRouter API
  5. Agent reads/writes files via bind-mount
  6. Host runs npm test and git commit/push after agent finishes
sequenceDiagram
    participant User
    participant Factory as Factory Agent
    participant Docker as Docker
    participant Container as Sandbox Container
    participant OR as OpenRouter
    participant GitHub

    User->>Factory: npm run sandbox:execute
    Factory->>Docker: Build image (if missing)
    Docker-->>Factory: Image ready
    Factory->>Factory: git clone / checkout
    Factory->>Docker: Start container
    Docker->>Container: Run tail -f /dev/null
    Factory->>Docker: docker exec openrouter-agent
    Docker->>Container: Execute agent
    Container->>OR: API call with prompt
    OR-->>Container: Tool calls requested
    Container->>Container: Read/Write files
    Container->>OR: Results
    OR-->>Container: Final response
    Container-->>Factory: JSON output
    Factory->>Factory: npm test
    Factory->>GitHub: git push + draft PR
Loading

6. Test HTTP Worker Locally

Start the server:

npm run dev:cloudflare

In another terminal:

npm run local:http-test -- --repo owner/repo --issue 123 --stage full

Default URL: http://localhost:3583

7. Quick Reference: What to Test When

What Changed Test Command
Prompts or roles npm run local:dry-run
Markers, labels, or writing npm run local:write-test
Cloning, git, verification, or PR flow npm run local:execute
HTTP entrypoint or Cloudflare wiring npm run dev:cloudflare + npm run local:http-test
Sandbox configuration npm run sandbox:execute

Deployment Guide

This repository builds a Cloudflare artifact using Flue. The build generates dist/ and sets up Wrangler redirection in .wrangler/deploy/config.json, so deployment can be launched from the repository root after building.

1. Prepare Credentials

Before deploying, ensure you have:

  • wrangler available
  • Logged into Cloudflare with npx wrangler login or equivalent environment variables
  • Required secrets and variables for the worker

2. Generate Build

npm run build:cloudflare

This produces:

  • dist/_entry.ts
  • dist/wrangler.jsonc
  • dist/manifest.json

3. Deploy to Cloudflare Workers

npx wrangler deploy

4. Configure Factory URL in GitHub

The workflow .github/workflows/issue-opened.yml needs this secret:

  • FACTORY_BASE_URL

It must point to the public URL of the deployed worker. That workflow makes a POST to:

${FACTORY_BASE_URL}/agents/factory/issue-<issue-number>

5. Configure Execution Workflow Secrets

The workflow .github/workflows/issue-ready-for-implementation.yml requires:

  • OPENROUTER_API_KEY
  • GITHUB_TOKEN

This job:

  • Checks out the repository
  • Installs dependencies with npm ci
  • Writes .env at runtime
  • Executes npm run local:execute

GitHub Actions Integration

issue-opened.yml

Triggered when:

  • An issue is opened
  • Manually via workflow_dispatch

Responsibility:

  • Calls the deployed factory
  • Initiates the planning pipeline with writeBack=true and stage=full

issue-ready-for-implementation.yml

Triggered when:

  • An issue receives the label factory:ready-for-implementation
  • Manually via workflow_dispatch

Responsibility:

  • Executes the Implement -> Review -> Ship pipeline
  • Pushes changes and opens draft PR

Managed Labels & Markers

Labels

Label Stage
factory:triaged Triage complete
factory:specified Spec complete
factory:planned Plan complete
factory:tasked Tasks complete
factory:ready-for-implementation Ready for execution
factory:implementing Implementation in progress
factory:reviewed-code Code review complete
factory:pr-opened Draft PR opened
factory:execution-failed Execution failed

Markers

<!-- rob-agent-factory:triage -->
<!-- rob-agent-factory:spec -->
<!-- rob-agent-factory:plan -->
<!-- rob-agent-factory:tasks -->
<!-- rob-agent-factory:implement -->
<!-- rob-agent-factory:review -->
<!-- rob-agent-factory:ship -->
<!-- rob-agent-factory:failure -->
<!-- rob-agent-factory:tasks-body:start -->
<!-- rob-agent-factory:tasks-body:end -->

Troubleshooting

Missing .env

cp .env.example .env

Missing Credentials

npm run local:validate

Local Worker Not Responding

  • Confirm npm run dev:cloudflare is running
  • Confirm the expected port is 3583
  • Re-run npm run local:http-test -- --repo owner/repo --issue 123

Execution Cannot Open PR

  • Verify gh works with the current token
  • Verify permissions: contents, pull-requests, and issues
  • Confirm the target repo allows push from the runner or local environment

Target Repo Fails Verification

This usually comes from the cloned project inside .factory-workspaces/, not this repo. Check there:

  • npm install
  • npm test
  • npm run build

Docker Sandbox Issues

Container exits immediately

Ensure the Docker image is built correctly:

npm run sandbox:build-image

Permission denied errors inside container

The container runs with your host UID. Ensure the image has a writable home:

RUN mkdir -p /home/agent && chmod 777 /home/agent

Image not found

The factory auto-builds the image on first run. To manually build:

npm run sandbox:build-image

Rate limit from OpenRouter

If you see 429 errors, the model is rate-limited upstream. Options:

  • Wait a few minutes and retry
  • Use a different model in .env:
FACTORY_MODEL=openrouter/openai/gpt-4o

References

About

An AI agent factory that processes open GitHub issues

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages