Platform Overview
Architecture and core components of the HeadlessOps platform
Platform Overview
HeadlessOps is a serverless automation runtime with a REST API, an MCP server, and a web UI. The platform is structured around Workspaces as the top-level isolation boundary.
Architecture
┌─────────────────────────────────────────────────┐
│ HeadlessOps │
│ │
│ ┌───────────────┐ ┌────────────────────────┐ │
│ │ REST API │ │ MCP Server │ │
│ │ /api/* │ │ OAuth 2.1 + PKCE │ │
│ └───────┬───────┘ └───────────┬────────────┘ │
│ │ │ │
│ ┌───────▼───────────────────────▼────────────┐ │
│ │ Platform Core │ │
│ │ Workspaces · Integrations · Credentials │ │
│ │ Runs · Data Stores · Knowledge Base │ │
│ └───────────────────────┬────────────────────┘ │
│ │ │
│ ┌───────────────────────▼────────────────────┐ │
│ │ TypeScript Step Runner │ │
│ │ Isolated V8 isolate per step │ │
│ │ ctx.http · ctx API · 30s timeout │ │
│ └────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘Key Components
Workspaces
A workspace is a self-contained tenant environment. All resources (integrations, credentials, data stores, knowledge base) are scoped to a workspace. A user can belong to multiple workspaces with different roles in each.
Each workspace has:
- A unique
id(CUID) andslug(URL-friendly name) - A member roster with role assignments (OWNER, ADMIN, DEVELOPER, MEMBER, VIEWER)
- API keys scoped to that workspace
- Isolated credentials vault, data stores, and knowledge base
Integrations
An integration is the core unit of automation. It consists of:
- An
integration.yamlmanifest — defines trigger type, step graph, and routing - One or more TypeScript step files (
step_id.ts) — each step isasync function run(input, ctx) - Optional supporting files — helpers, config,
knowledge_base.md,fix_log.md
my-automation/
integration.yaml # Required — manifest
step_one.ts # TypeScript step (must match step id)
step_two.ts
helpers.ts # Optional — shared utilities
knowledge_base.md # Recommended — documents design and schemas
fix_log.md # Required when debuggingRuns
Each time an integration is triggered (via webhook, schedule, or manual API call), a Run is created. Runs track:
| Field | Description |
|---|---|
status | PENDING → RUNNING → SUCCEEDED / FAILED / CANCELLED |
steps | Structured log per step with input, output, and timestamps |
output | Value set via ctx.output() (for synchronous webhooks) |
triggeredBy | webhook / schedule / manual |
The TypeScript Runtime
Each step runs in an isolated V8 TypeScript environment:
- Steps communicate through
ctx(credentials, logging, data stores, output, HTTP) - Steps pass data to each other via their return value:
${{ steps.STEP_ID.output.field }} - The runtime enforces a 30-second timeout per step
ctx.httpis the built-in HTTP client, auto-instrumented for request tracing
API Authentication
Two authentication modes are supported:
| Mode | Header / Cookie | Use Case |
|---|---|---|
| API Key | Authorization: Bearer iter_<key> | Programmatic access, MCP, CI/CD |
| Session | Cookie after POST /api/auth/sign-in/email | Browser-based web app |
API keys are scoped to a workspace and automatically resolve the workspace — you do not need to pass workspaceId with API key requests.
Integration Lifecycle
create ──▶ push files ──▶ deploy ──▶ trigger ──▶ run ──▶ logs
│ │
└──── push-run (atomic) ───┘| Step | API Endpoint | Description |
|---|---|---|
| Create | POST /api/integrations | Register a new integration by name |
| Push files | PUT /api/integrations/:name/files/:filename | Upload individual files |
| Deploy | POST /api/integrations/:name/deploy | Snapshot current files as a versioned deployment |
| Push-run | POST /api/integrations/:name/push-run | Atomic: push + deploy + trigger a run |
| Trigger | POST /api/integrations/:name/runs | Trigger a manual run |
| Activate | POST /api/integrations/:name/activate | Enable webhook/schedule processing |
Platform Data Flow
External Event (webhook/cron/manual)
│
▼
Integration Trigger
│
▼
Step 1: fetch_data.ts
│ ctx.credentials.MY_API_KEY
│ ctx.log("fetched", {...})
│ return {"record": {...}}
│
▼ ${{ steps.step_1.output.record }}
Step 2: process.ts
│ ctx.stores.processed_records.find_one(...)
│ ctx.stores.processed_records.insert(...)
│ return {"status": "ok"}
│
▼
Run completed → SUCCEEDEDSupported Trigger Types
| Type | How It Fires | YAML trigger.type |
|---|---|---|
| Webhook | HTTP POST/GET to /api/hooks/{workspaceId}/{name} | webhook |
| Schedule | Cron expression in UTC | schedule |
| Manual | API call or web UI | manual |
What Makes HeadlessOps Different
- AI-native — every operation is available as an MCP tool for AI agents
- Code-first — automations are TypeScript files, not drag-and-drop blocks
- Deterministic — no magic. Steps run in order, data flows explicitly
- Observable — every step produces structured logs visible in the run history
- Idempotency-ready — data stores let you track what's been processed