Workspace API Reference
This page provides a complete REST API reference for workspace operations, including file management, command execution, GitHub integration, and task orchestration. For conceptual overviews of these features, see Workspace Worker Architecture, GitHub Integration, File Operations, Command Execution, and Task Management.
API Architecture
The workspace API is organized into two tiers: a public orchestrator API that handles authentication and request routing, and an internal worker API that executes operations on the persistent volume. Most operations are synchronous proxies (file I/O, command exec), while long-running tasks (git clone, multi-step workflows) use an async queue-based system.
Two-Tier API Design
Sources: orchestrator/api/workspace_files.py:1-108, orchestrator/api/workspace_github.py:1-294, orchestrator/api/tasks.py:1-396, orchestrator/core/workspace_client.py:1-191, services/workspace-worker/main.py:461-700
File Operations API
Endpoints for browsing workspace files, reading content, and executing commands. All operations are scoped to a single workspace identified by {workspace_id} in the URL path.
GET /api/workspaces/{workspace_id}/files
List directory contents at a given path within the workspace.
Request:
Query Parameters:
path
string
No
"."
Relative path inside workspace (workspace-root-relative)
Response (200 OK):
Error Responses:
403 Forbidden- Workspace access denied (mismatched workspace_id)404 Not Found- Directory does not exist503 Service Unavailable- Worker unreachable
Sources: orchestrator/api/workspace_files.py:30-51, services/workspace-worker/executor.py:272-300
GET /api/workspaces/{workspace_id}/files/content
Read the text content of a file for code viewing or processing.
Request:
Query Parameters:
path
string
Yes
Relative file path inside workspace
Response (200 OK):
Truncation: Content is capped at 500KB by default. If truncated: true, only the first 500KB is returned.
Error Responses:
400 Bad Request- Path traversal detected (e.g.../../../etc/passwd)403 Forbidden- Workspace access denied404 Not Found- File does not exist503 Service Unavailable- Worker unreachable
Sources: orchestrator/api/workspace_files.py:54-74, services/workspace-worker/executor.py:230-252
POST /api/workspaces/{workspace_id}/exec
Execute a sandboxed shell command in the workspace. Only whitelisted commands are allowed (see Security & Sandboxing).
Request:
Request Body (ExecRequest):
command
string
Yes
-
1-4096 chars
Shell command to execute
cwd
string
No
workspace root
-
Working directory (relative to workspace)
timeout
integer
No
120
1-300
Max execution time in seconds
Response (200 OK):
Output Limits:
stdout: Max 100KBstderr: Max 50KBIf output exceeds limits,
truncated: trueand content is trimmed
Command Whitelist: Only approved binaries can execute: git, python, node, npm, pytest, ls, cat, grep, etc. See ALLOWED_COMMANDS in executor.py:35-73 for the full list.
Blocked Patterns: Certain dangerous patterns are blocked even if the binary is whitelisted: sudo, rm -rf /, chmod 777, etc. See BLOCKED_PATTERNS in executor.py:76-95.
Error Responses:
400 Bad Request- Command not whitelisted or blocked pattern detected403 Forbidden- Workspace access denied503 Service Unavailable- Worker unreachable
Sources: orchestrator/api/workspace_files.py:77-107, services/workspace-worker/executor.py:122-224
GitHub Integration API
Endpoints for browsing GitHub repositories via Composio OAuth and cloning them into the workspace.
GitHub Repository Object
All GitHub endpoints return repositories in this format:
GET /api/workspaces/{workspace_id}/github/repos
List GitHub repositories accessible to the authenticated user via Composio.
Request:
Query Parameters:
page
integer
No
1
≥1
Page number for pagination
per_page
integer
No
30
1-100
Repositories per page
Response (200 OK):
Prerequisites:
Workspace must have GitHub connected via Composio (
EntityConnectionwithcomposio_entity_id)User must have authorized GitHub OAuth via Composio app assignment
Error Responses:
403 Forbidden- Workspace access denied404 Not Found- No Composio entity found for workspace (GitHub not connected)501 Not Implemented- Composio SDK not installed502 Bad Gateway- GitHub API error
Sources: orchestrator/api/workspace_github.py:97-161, orchestrator/core/composio/entity_manager.py
POST /api/workspaces/{workspace_id}/github/clone
Clone a GitHub repository into the workspace via task submission. Supports both public and private repos (private requires GitHub OAuth token from Composio).
Request:
Request Body (CloneRequest):
repo_url
string
Yes
HTTPS only, allowed hosts
Git clone URL (HTTPS)
branch
string
No
Safe branch pattern
Branch to clone (default: repo default)
URL Validation:
Scheme must be
https://Host must be in allowlist:
github.com,gitlab.com,bitbucket.orgNo embedded credentials (username:password in URL)
Branch Validation:
Must match pattern:
^[A-Za-z0-9._/\-]+$Cannot contain
..,@{, or leading-
Response (200 OK):
Execution Flow:
Orchestrator attempts to retrieve GitHub OAuth token from Composio
If token found, injects into HTTPS URL:
https://x-access-token:{token}@github.com/...Submits
git_clonetask to Redis queue with injected URLWorker executes:
git clone --depth 1 --branch {branch} -- {url} /workspaces/{id}/repos/{name}Task transitions:
queued→running→completed
Token Injection Security (PRD-70):
OAuth token is injected server-side (never exposed to client)
URL uses
x-access-tokenauthentication formatWorker executes with
--separator to prevent argument injectionBranch name validated to prevent
--upload-packinjection attacks
Error Responses:
400 Bad Request- Invalid URL, branch, or worker backend notqueued403 Forbidden- Workspace access denied404 Not Found- No Composio entity for workspace503 Service Unavailable- Redis enqueue failed
Sources: orchestrator/api/workspace_github.py:167-293, services/workspace-worker/executor.py:368-419
Task Management API
Endpoints for submitting workspace tasks, monitoring execution, and streaming real-time events.
Task Lifecycle State Machine
POST /api/tasks/submit
Submit a workspace task with explicit steps for immediate execution. Bypasses LLM agent — runs steps directly on the worker.
Request:
Request Body (SubmitTaskRequest):
steps
array
Yes
-
≥1 step
Steps to execute in order
priority
string
No
"normal"
low, normal, high, critical
Queue priority
timeout_seconds
integer
No
300
10-3600
Max execution time
Step Actions:
execute_command
command
cwd, timeout
Run shell command
git_clone
repo
branch, shallow
Clone git repository
git_pull
repo_name
branch
Pull latest changes
read_file
path
-
Read file content
write_file
path, content
-
Write or create file
list_directory
-
path
List directory entries
create_directory
path
-
Create directory
Response (200 OK):
Queue Priority: Tasks are enqueued to priority-specific Redis lists:
workspace:tasks:critical— dequeued firstworkspace:tasks:highworkspace:tasks:normal(default)workspace:tasks:low
Atomic Submission: Task row is inserted into task_executions table before Redis enqueue. If Redis enqueue fails, the DB row is marked failed with error message.
Prerequisites:
TASK_RUNNER_BACKEND=queued(returns 400 if local/kubernetes backend)
Error Responses:
400 Bad Request- Invalid steps, wrong backend, or validation failure503 Service Unavailable- Redis queue unavailable
Sources: orchestrator/api/tasks.py:62-173, services/workspace-worker/main.py:227-357
GET /api/tasks
List recent tasks for the current workspace with optional filtering.
Request:
Query Parameters:
status
string
No
-
queued, running, completed, failed, timed_out, cancelled
Filter by status
task_type
string
No
-
-
Filter by task type
limit
integer
No
20
1-100
Results per page
offset
integer
No
0
≥0
Pagination offset
Response (200 OK):
Ordering: Tasks are returned in reverse chronological order (newest first) by submitted_at.
Sources: orchestrator/api/tasks.py:176-247
GET /api/tasks/{task_id}
Get full task detail including result payload and execution metadata.
Request:
Response (200 OK):
Result Structure: The result field contains:
status: Final status (completed, failed, timed_out)result.steps: Array of step results with stdout/stderr/exit codesresult.repos_cached: List of repositories cached in workspaceexecution_time_ms: Total execution time in millisecondserror: Error message if any step failed
Error Responses:
404 Not Found- Task not found or workspace mismatch
Sources: orchestrator/api/tasks.py:250-298
POST /api/tasks/{task_id}/cancel
Cancel a queued or running task. Cancellation is best-effort: queued tasks are guaranteed to cancel, running tasks check between steps.
Request:
Response (200 OK):
Cancellation Behavior:
queued
Status updated to cancelled in Redis. Worker skips on dequeue.
running
Status updated to cancelled in Redis. Worker checks between steps and aborts.
completed, failed, timed_out
Returns 400 (already terminal state)
Inter-Step Cancellation: Workers check Redis status between each step execution. If status is cancelled, the worker publishes a status_changed event and stops execution.
Error Responses:
400 Bad Request- Task already in terminal state404 Not Found- Task not found or workspace mismatch
Sources: orchestrator/api/tasks.py:304-355, services/workspace-worker/main.py:282-285
GET /api/tasks/{task_id}/events
Server-Sent Events (SSE) stream of real-time task execution events. Subscribe to this endpoint to receive progress updates, status changes, and error notifications.
Request:
Response (200 OK - SSE Stream):
Event Types:
status_changed
status
Task transitioned to new status
progress_update
step, total_steps, description
Step execution started
error
error, step (optional)
Error occurred during step
Event Schema:
Stream Lifecycle:
Client connects, receives
connectedSSE commentWorker publishes events to Redis channel
workspace:task:{task_id}:eventsOrchestrator subscribes to channel and forwards as SSE
On task completion/failure, stream sends final event and closes
If task already complete when client connects, sends final state immediately
Timeout: Stream auto-closes after 10 minutes of inactivity or when task reaches terminal state.
Error Responses:
404 Not Found- Task not found or workspace mismatch
Sources: orchestrator/api/tasks.py:358-396, services/workspace-worker/main.py:422-434
Request/Response Models
Pydantic Schemas
All request bodies are validated using Pydantic models defined in the endpoint files.
ExecRequest (workspace_files.py:80-83):
CloneRequest (workspace_github.py:65-91):
TaskStep (tasks.py:39-49):
SubmitTaskRequest (tasks.py:52-56):
Sources: orchestrator/api/workspace_files.py:80-83, orchestrator/api/workspace_github.py:65-91, orchestrator/api/tasks.py:39-56
Error Handling
All endpoints follow a consistent error response format.
HTTP Status Codes
200
OK
Successful operation
400
Bad Request
Invalid parameters, validation failure, wrong backend
403
Forbidden
Workspace access denied (X-Workspace-ID mismatch)
404
Not Found
Resource not found (task, file, directory, Composio entity)
501
Not Implemented
Composio SDK not installed
502
Bad Gateway
External API error (GitHub, Composio)
503
Service Unavailable
Worker unreachable, Redis queue unavailable
Error Response Format
FastAPI HTTPException: All errors are raised as HTTPException with appropriate status code and detail message.
Worker Connection Errors: When the workspace worker is unreachable, the WorkspaceClient returns:
Sources: orchestrator/core/workspace_client.py:47-53, orchestrator/api/workspace_files.py:42-49
Authentication & Authorization
Clerk JWT Authentication
All workspace endpoints require Clerk JWT authentication via the Authorization: Bearer {token} header.
Request Context Extraction:
Workspace Isolation: Every endpoint validates that ctx.workspace_id matches the {workspace_id} path parameter before executing operations. This ensures users can only access their own workspaces.
Internal Worker Authentication: Requests from orchestrator to worker use X-Internal-Token header (not Clerk JWT). This token is configured via WORKER_INTERNAL_TOKEN environment variable.
Sources: orchestrator/api/workspace_files.py:19-42, orchestrator/core/workspace_client.py:33-38
Internal Worker HTTP API
While most operations proxy through the orchestrator API, the workspace worker also exposes a direct HTTP API on port 8081. This is internal-only and should not be exposed to public internet.
Worker Endpoints
GET
/health
Health check with worker stats
GET
/workspaces/{id}/files
List directory (direct, no auth check)
GET
/workspaces/{id}/files/content
Read file content (direct)
POST
/workspaces/{id}/exec
Execute command (direct)
GET
/workspaces/{id}/grep
Search files with regex pattern
Authentication: All worker endpoints check for X-Internal-Token header. If configured, unauthorized requests return 403.
Health Endpoint Response:
Grep Endpoint: Provides regex search across workspace files:
Response:
Sources: services/workspace-worker/main.py:461-700
WorkspaceClient Proxy
The orchestrator uses WorkspaceClient to proxy requests to the worker HTTP API. This provides a typed, async interface for backend code.
Usage Example
Available Methods
read_file(path)
path: str
Dict[str, Any]
write_file(path, content)
path: str, content: str
Dict[str, Any]
list_dir(path)
path: str
Dict[str, Any]
exec_command(command, cwd, timeout)
command: str, cwd: Optional[str], timeout: int
Dict[str, Any]
grep(pattern, path, include, max_results)
pattern: str, ...
Dict[str, Any]
Connection Pooling: WorkspaceClient uses a singleton httpx.AsyncClient shared across all instances. Connection is reused for performance.
Timeout Configuration:
Connect: 10 seconds
Read: 130 seconds (allows for long command execution)
Write: 30 seconds
Pool: 10 seconds
Error Handling: All methods return {"success": False, "error": "..."} on connection/timeout errors. Callers should check for this pattern.
Sources: orchestrator/core/workspace_client.py:1-191
Rate Limiting (Widget API)
Widget SDK endpoints (/api/widgets/*) have per-API-key rate limiting enforced by WidgetRateLimitMiddleware.
Limits:
Public keys (
ak_pub_*): 30 requests/minuteServer keys (
ak_srv_*): 1000 requests/minuteUnauthenticated (IP-based): 30 requests/minute
Rate Limit Headers:
429 Response:
Sliding Window: Uses in-memory sliding window counter with 60-second window size. Requests older than 60 seconds are dropped from the window.
Sources: orchestrator/api/widgets/rate_limit.py:1-166
Request Flow Examples
File Read Flow
Sources: orchestrator/api/workspace_files.py:54-74, orchestrator/core/workspace_client.py:68-78, services/workspace-worker/executor.py:230-252
GitHub Clone Flow
Sources: orchestrator/api/workspace_github.py:167-293, services/workspace-worker/main.py:227-357, services/workspace-worker/executor.py:368-419
See Also
Workspace Worker Architecture - Internal architecture of the workspace worker service
GitHub Integration - Conceptual overview of GitHub OAuth and cloning
File Operations - File system security and operations
Command Execution - Command whitelisting and sandboxing
Security & Sandboxing - Five-layer security model
Task Management - Task lifecycle and queue system
Last updated

