Cloud Agents
v3.8.1Last updated: 2026-05-13
Was this page helpful?
Loading OmniRoute...
Source of truth: and
Last updated: 2026-05-13 β v3.8.0
not a regular chat completion. It is a durable, multi-step unit of work that may take minutes to hours, can produce a Pull Request as its artifact, and supports follow-up messages and (in some providers) plan approval gates.
diagrams/cloud-agent-flow.mmd
β exports ,
, and . The registry is a
plain in-memory populated at module load.
lazy: status is refreshed from the upstream on every .
There is no background poller. Dashboards that need fresh state should poll the GET
endpoint at a sensible interval.
export interface AgentCredentials {
apiKey: string;
baseUrl?: string;
}
export interface CreateTaskParams {
prompt: string;
source: CloudAgentSource;
options: {
autoCreatePr?: boolean;
planApprovalRequired?: boolean;
environment?: Record<string, string>;
};
}
export interface GetStatusResult {
status: CloudAgentStatus;
externalId?: string;
result?: CloudAgentResult;
activities: CloudAgentActivity[];
error?: string;
}
export abstract class CloudAgentBase {
abstract readonly providerId: string;
abstract readonly baseUrl: string;
abstract createTask(p: CreateTaskParams, c: AgentCredentials): Promise<CloudAgentTask>;
abstract getStatus(externalId: string, c: AgentCredentials): Promise<GetStatusResult>;
abstract approvePlan(externalId: string, c: AgentCredentials): Promise<void>;
abstract sendMessage(
externalId: string,
message: string,
c: AgentCredentials
): Promise<CloudAgentActivity>;
abstract listSources(
c: AgentCredentials
): Promise<{ name: string; url: string; branch?: string }[]>;
protected mapStatus(raw: string): CloudAgentStatus; // heuristic upstream-string β enum
protected generateTaskId(): string; // `task_<ts>_<rand>`
protected generateActivityId(): string; // `act_<ts>_<rand>`
}
intentionally throws β Codex Cloud auto-plans and has
no approval gate. returns .
export const CLOUD_AGENT_STATUS = {
QUEUED: "queued",
RUNNING: "running",
AWAITING_APPROVAL: "awaiting_approval",
COMPLETED: "completed",
FAILED: "failed",
CANCELLED: "cancelled",
} as const;
export interface CloudAgentSource {
repoName: string;
repoUrl: string; // must be a valid URL
branch?: string;
}
export interface CloudAgentResult {
prUrl?: string;
prNumber?: number;
commitMessage?: string;
diffUrl?: string;
summary?: string;
duration?: number; // seconds, positive int
cost?: number; // positive float
}
export interface CloudAgentActivity {
id: string;
type: "plan" | "command" | "code_change" | "message" | "error" | "completion";
content: string;
timestamp: string; // ISO 8601
metadata?: Record<string, unknown>;
}
export interface CloudAgentTask {
id: string; // internal `task_...` id
providerId: "jules" | "devin" | "codex-cloud";
externalId?: string; // upstream provider's id
status: CloudAgentStatus;
prompt: string; // 1..10000 chars
source: CloudAgentSource;
options: {
autoCreatePr?: boolean;
planApprovalRequired?: boolean;
environment?: Record<string, string>;
};
result?: CloudAgentResult;
activities: CloudAgentActivity[];
error?: string;
createdAt: string;
updatedAt: string;
completedAt?: string;
}
, ) are
exported alongside the types and are used by the route handlers.
β table is created lazily via
(also called from at
module import).
CREATE TABLE IF NOT EXISTS cloud_agent_tasks (
id TEXT PRIMARY KEY,
provider_id TEXT NOT NULL,
external_id TEXT,
status TEXT NOT NULL DEFAULT 'queued',
prompt TEXT NOT NULL,
source TEXT NOT NULL, -- JSON
options TEXT DEFAULT '{}', -- JSON
result TEXT, -- JSON
activities TEXT DEFAULT '[]', -- JSON
error TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
completed_at TEXT
);
CREATE INDEX IF NOT EXISTS idx_cloud_agent_tasks_provider ON cloud_agent_tasks(provider_id);
CREATE INDEX IF NOT EXISTS idx_cloud_agent_tasks_status ON cloud_agent_tasks(status);
CREATE INDEX IF NOT EXISTS idx_cloud_agent_tasks_created ON cloud_agent_tasks(created_at DESC);
enforces a column whitelist to prevent SQL injection:
, , , , , , ,
. Any other key in the partial update is silently dropped.
Auth: All endpoints require management auth
( wraps from
). This is enforced after commit
("fix(auth): require management auth for agent and cooldown APIs").
, , |
||
| not cancel upstream) | ||
/ / |
||
curl -X POST http://localhost:20128/api/v1/agents/tasks \
-H "Cookie: auth_token=..." \
-H "Content-Type: application/json" \
-d '{
"providerId": "devin",
"prompt": "Fix the bug in src/foo.ts where the parser returns null",
"source": {
"repoName": "user/repo",
"repoUrl": "https://github.com/user/repo",
"branch": "main"
},
"options": {
"autoCreatePr": true,
"planApprovalRequired": false
}
}'
:
{
"data": {
"id": "task_1731512345678_abc123def",
"providerId": "devin",
"externalId": "session_xyz",
"status": "queued",
"prompt": "...",
"source": { "repoName": "user/repo", "repoUrl": "...", "branch": "main" },
"options": { "autoCreatePr": true },
"createdAt": "2026-05-13T12:34:56.789Z"
}
}
curl -X POST http://localhost:20128/api/v1/agents/tasks/<id> \
-H "Cookie: auth_token=..." \
-H "Content-Type: application/json" \
-d '{"action":"approve"}'
curl -X POST http://localhost:20128/api/v1/agents/tasks/<id> \
-d '{"action":"message","message":"Also add a unit test for the parser"}'
curl -X POST http://localhost:20128/api/v1/agents/tasks/<id> \
-d '{"action":"cancel"}'
flips to in the local DB but does not call the
upstream provider β there is no abort RPC in . To stop billing
upstream, terminate the task in the provider's own console.
are used by remote clients
(the CLI, the Electron app, or sync workers) to read provider connection metadata
and resolve model aliases. They are authenticated with a regular API key
(via ), not the management auth used by the task endpoints.
/ / |
||
never returns raw / / . It
returns , , , and a masked preview
(: first 4 + + last 4).
in :
. with
.
and a populated .
React page that:
, , ,
, ) and renders the timeline. / when . handler to and translates A2A task
status events to the JSON-RPC 2.0 protocol. See A2A-SERVER.md.
.
- ,
, (or throw if N/A),
, . Use for status normalization.
- under a stable
.
- literal union in
( and ).
- if it needs a connection
record. OAuth-based providers also need
.
- .
- constant.
table.