Forge is a platform for running AI coding agents in isolated Kubernetes containers. It provides stateless orchestration for OpenCode agents, enabling remote agent execution with real-time streaming via webhooks.
┌─────────────────┐ ┌─────────────────────────────────────────────────────────┐
│ Your App │ │ FORGE │
│ │ HTTP POST │ ┌─────────────────┐ gRPC ┌───────────────┐ │
│ - Stores msgs │────────────────>│ │ Platform │<───────────────>│ Agent (Pod) │ │
│ - Business │ │ │ (Go) │ Bidirectional │ (OpenCode) │ │
│ logic │ Webhook POST │ └─────────────────┘ Stream └───────────────┘ │
│ - User mgmt │<────────────────│ │ │ │
│ │ (async events) │ ▼ ▼ │
└─────────────────┘ │ ┌─────────────────┐ ┌───────────────┐ │
│ │ Kubernetes │ │ Claude API │ │
│ └─────────────────┘ └───────────────┘ │
└─────────────────────────────────────────────────────────┘
How it works:
- Your app sends a message to an agent via HTTP POST
- Platform returns
202 Acceptedimmediately - Platform streams the request to the agent pod via gRPC
- Agent processes with Claude and streams events back
- Platform delivers each event to your webhook URL
- Final event includes
is_final: true
forge/
├── platform/ # Go orchestration service (Echo, Uber Fx, Connect-RPC)
│ ├── cmd/server/ # Entry point
│ └── internal/
│ ├── agent/ # Agent lifecycle & messaging
│ ├── k8s/ # Kubernetes client
│ └── webhook/ # Webhook delivery
├── agent/claudecode/ # TypeScript agent (Bun, Fastify, OpenCode SDK)
│ └── src/
│ ├── services/ # gRPC handlers
│ └── opencode/ # OpenCode event handling
└── proto/agent/v1/ # Protocol Buffer definitions
- Go 1.23+, Bun 1.0+, Docker
- Kubernetes cluster (or k3d for local dev)
- Anthropic API key
# Clone and setup
git clone https://github.com/notzree/forge.git
cd forge
cp .env.example .env
# Add your ANTHROPIC_API_KEY to .env
# Install dependencies and start
just setup
just devThis creates a k3d cluster, builds the agent image, and starts the platform.
curl -X POST http://localhost:8080/api/v1/agents \
-H "Content-Type: application/json" \
-d '{"owner_id": "user123"}'curl "http://localhost:8080/api/v1/agents?user_id=user123"curl "http://localhost:8080/api/v1/agents/{agent_id}?user_id=user123"curl -X DELETE "http://localhost:8080/api/v1/agents/{agent_id}?user_id=user123"curl -X POST "http://localhost:8080/api/v1/agents/{agent_id}/messages?user_id=user123" \
-H "Content-Type: application/json" \
-d '{
"content": "Create a hello world Python script",
"webhook_url": "https://your-app.com/webhook",
"webhook_secret": "optional-hmac-secret"
}'Response: 202 Accepted
{"request_id": "req_abc123", "agent_id": "a1b2c3d4", "status": "processing"}Webhook payloads delivered to your endpoint:
{
"event_type": "agent.event",
"agent_id": "a1b2c3d4",
"request_id": "req_abc123",
"seq": 1,
"is_final": false,
"opencode_event_type": "message.part.updated",
"event": { "type": "message.part.updated", "properties": { ... } }
}Event types: agent.event (OpenCode events), agent.error, agent.complete
curl -X POST "http://localhost:8080/api/v1/agents/{agent_id}/interrupt?user_id=user123" \
-H "Content-Type: application/json" \
-d '{"webhook_url": "https://your-app.com/webhook"}'| Webhooks | WebSockets |
|---|---|
| Platform stays stateless | Requires connection state |
Built-in retry, seq for ordering |
Lost messages on disconnect |
| Scales horizontally | Needs sticky sessions |
| Any HTTP endpoint works | Requires WS infrastructure |
Trade-off: Higher latency per event, but coding agents run for minutes anyway.
- Your app owns the data (messages, history, users)
- Platform scales horizontally without shared state
- No database to operate
- Isolation: dedicated resources and filesystem per user
- Simplicity: no session multiplexing
- Security: environment isolation between users
Trade-off: Cold start latency when spinning up new pods.
| Feature | Status |
|---|---|
| File/image attachments | Not implemented |
| Session history retrieval | Not implemented |
| Permission request handling | Auto-approved (events streamed but no reply API) |
| Git authentication | Not implemented (use env vars as workaround) |
| API authentication | Not implemented |
just dev # Start local k3d + platform
just dev-rebuild # Rebuild agent image and restart
just run-platform # Run platform only
just run-agent # Run agent locally
just proto # Generate protobuf code
just --list # All commandsMIT