Build on the OpenForge API
A RESTful API with first-class SSE streaming. Eight core endpoints, 16+ event types, and copy-paste examples in Python, JavaScript, curl, and Go.
http://localhost:8000/apiAll endpoints are prefixed with /api. Bearer auth via Authorization: Bearer <token> header is required unless noted.
Core endpoints
Click any row to copy its full URL to your clipboard.
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | /api/skills | List all 40 skills with metadata, category, and tags. | Required |
| POST | /api/skills/{name}/execute | Execute a named skill with the provided input payload. | Required |
| GET | /api/sessions | List all persisted sessions with metadata and timestamps. | Required |
| POST | /api/chat | Send a chat message — returns SSE stream of events. | Required |
| GET | /api/memory | Read MEMORY.md, USER.md, and PROCEDURES.md files. | Required |
| POST | /api/memory | Write or append to memory files (HITL-protected). | Required |
| GET | /api/providers | List configured LLM providers with status and models. | Required |
| GET | /api/health | Liveness + readiness probe for load balancers. | Open |
Code examples
Pick your language — every example lists skills, executes one, and streams a chat response.
import requests
import json
BASE = "http://localhost:8000/api"
TOKEN = "openforge_your_bearer_token"
HEADERS = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
}
# 1. List all 40 skills
r = requests.get(f"{BASE}/skills", headers=HEADERS)
skills = r.json()
print(f"{len(skills)} skills available")
# 2. Execute a skill
r = requests.post(
f"{BASE}/skills/code_review/execute",
headers=HEADERS,
json={"input": {"file": "main.py", "content": "print('hi')"}},
)
print(r.json()["output"])
# 3. Stream a chat response (SSE)
with requests.post(
f"{BASE}/chat",
headers={**HEADERS, "Accept": "text/event-stream"},
json={"message": "Explain this codebase", "stream": True},
stream=True,
) as resp:
for line in resp.iter_lines():
line = line.decode()
if line.startswith("data:"):
evt = json.loads(line[5:].strip())
print(evt.get("delta", ""), end="", flush=True)pythonSSE event types
The /api/chat stream emits 16+ structured Server-Sent Events. Each event has a stable type and a JSON data payload.
session.startEmitted when a new session is created. Contains session_id and persona.
event: session.start
data: {"session_id":"sess_99","persona":"architect","ts":"2025-02-14T09:42:11Z"}session.endEmitted when a session is closed or expires.
event: session.end
data: {"session_id":"sess_99","reason":"user_close"}message.startMarks the beginning of an assistant message.
event: message.start
data: {"message_id":"msg_42","role":"assistant"}message.deltaStreamed token / chunk of the assistant message.
event: message.delta
data: {"message_id":"msg_42","delta":"Hello"}message.endMarks the end of an assistant message with stats.
event: message.end
data: {"message_id":"msg_42","tokens":142,"duration_ms":1820}think.startAgent begins an internal reasoning step (visible in TUI).
event: think.start
data: {"step":"planning","persona":"architect"}think.deltaStreamed reasoning token.
event: think.delta
data: {"delta":"Analyzing codebase..."}think.endAgent finished reasoning, about to act.
event: think.end
data: {"duration_ms":420}tool.startA tool is about to be invoked.
event: tool.start
data: {"tool":"file_read","args":{"path":"main.py"}}tool.endA tool finished, returns its result summary.
event: tool.end
data: {"tool":"file_read","ok":true,"bytes":2048}tool.approvalHITL approval requested for a destructive tool.
event: tool.approval
data: {"tool":"terminal_exec","command":"rm -rf build","risk":"high"}skill.invokeAn AI skill (e.g. code_review) is being executed.
event: skill.invoke
data: {"skill":"code_review","target":"main.py"}provider.swapActive LLM provider was changed at runtime.
event: provider.swap
data: {"from":"openai","to":"anthropic","reason":"rate_limit"}memory.writeA memory file was updated.
event: memory.write
data: {"file":"MEMORY.md","bytes":512,"append":true}errorNon-fatal error during streaming (agent may continue).
event: error
data: {"code":"tool_timeout","tool":"web_search","retry":true}doneTerminal event — stream is now closed.
event: done
data: {"tokens":1240,"duration_ms":3840}Request & response examples
The /api/chat endpoint is the workhorse — here's exactly what goes in and what comes out.
# POST /api/chat — request body
{
"message": "Refactor this function for readability",
"session_id": "sess_99", // optional, omit to create new
"persona": "architect", // optional, default: user's last
"provider": "anthropic", // optional, default: configured
"stream": true, // SSE stream (recommended)
"context": { // optional, additional context
"files": ["src/main.ts"],
"selections": [{"path":"src/main.ts","start":12,"end":42}]
},
"tools": { // optional, tool overrides
"allow": ["file_read", "file_patch"],
"deny": ["terminal_exec"]
},
"memory": { // optional, memory overrides
"recall": true, // fetch relevant memories
"write": true // allow writing to MEMORY.md
}
}json# POST /api/chat — non-streaming response
{
"session_id": "sess_99",
"message_id": "msg_42",
"role": "assistant",
"content": "Here's a cleaner version of the function:\n\n...",
"persona": "architect",
"provider": "anthropic",
"model": "claude-3-5-sonnet-20241022",
"tokens": { "input": 312, "output": 184, "total": 496 },
"duration_ms": 1820,
"tools_used": [
{"tool": "file_read", "ok": true, "duration_ms": 18},
{"tool": "file_patch", "ok": true, "duration_ms": 42}
],
"memory_updated": ["MEMORY.md"],
"confidence": 0.92
}
# Error response (HTTP 4xx / 5xx)
{
"error": {
"code": "rate_limited",
"message": "Provider rate limit reached. Retry in 12s.",
"retry_after": 12,
"request_id": "req_8f3a2b"
}
}jsonExecute a skill
Every skill accepts a JSON input payload and returns a structured output. See the Skills Catalog for per-skill schemas.
# POST /api/skills/{name}/execute — request
{
"input": {
"file": "src/auth/login.ts",
"content": "export function login(u,p){return fetch(...)}",
"focus": ["security", "readability"]
},
"session_id": "sess_99", // optional
"provider": "anthropic" // optional
}json# POST /api/skills/code_review/execute — response
{
"skill": "code_review",
"output": {
"summary": "2 security issues, 3 style improvements.",
"findings": [
{
"severity": "high",
"category": "security",
"line": 1,
"message": "Credentials sent over unencrypted fetch().",
"suggestion": "Use HTTPS and never inline credentials."
},
{
"severity": "medium",
"category": "style",
"line": 1,
"message": "Function parameters are single letters.",
"suggestion": "Rename to (username, password)."
}
],
"score": 62,
"passed": false
},
"tokens": { "input": 184, "output": 312 },
"duration_ms": 2480,
"request_id": "req_8f3a2b"
}jsonReady to build?
Spin up a local OpenForge in under 60 seconds, then start hitting the API. All endpoints work identically on localhost and in production.