feat(sdk): cloud endpoints, API executor, and Communicate SDK v2 protocol#632
feat(sdk): cloud endpoints, API executor, and Communicate SDK v2 protocol#632khaliqgant merged 8 commits intomainfrom
Conversation
Two new SDK features:
1. cli: 'api' — direct provider API calls via fetch()
- Anthropic, OpenAI, Google supported (detected from model name)
- skills field → system prompt per agent
- No sandbox, no CLI, instant execution
2. cloud: true — run workflows in cloud sandboxes
- Submit via cloud API, poll for results
- Same WorkflowRunRow shape as local execution
- envSecrets for secure API key injection
Usage:
.agent('worker', { cli: 'api', model: 'claude-sonnet-4-20250514', skills: '...' })
.run({ cloud: true, envSecrets: { ANTHROPIC_API_KEY: '...' } })
AgentCli type includes 'api' but CLI_REGISTRY (Record<AgentCli, ...>) was missing the entry, causing tsc build failure.
| if (specialistDef.cli === 'api') { | ||
| const stepOutputContext = this.buildStepOutputContext(stepStates, runId); | ||
| const resolvedTask = this.interpolateStepTask(step.task ?? '', stepOutputContext); | ||
|
|
||
| state.row.status = 'running'; | ||
| state.row.startedAt = new Date().toISOString(); | ||
| await this.db.updateStep(state.row.id, { | ||
| status: 'running', | ||
| startedAt: state.row.startedAt, | ||
| updatedAt: new Date().toISOString(), | ||
| }); | ||
| this.emit({ type: 'step:started', runId, stepName: step.name }); | ||
| this.postToChannel(`**[${step.name}]** Started (api)`); | ||
|
|
||
| const output = await executeApiStep( | ||
| specialistDef.constraints?.model ?? 'claude-sonnet-4-20250514', | ||
| resolvedTask, | ||
| { envSecrets: this.envSecrets, skills: specialistDef.skills }, | ||
| ); | ||
|
|
||
| state.row.status = 'completed'; | ||
| state.row.output = output; | ||
| state.row.completedAt = new Date().toISOString(); | ||
| await this.db.updateStep(state.row.id, { | ||
| status: 'completed', | ||
| output, | ||
| completedAt: state.row.completedAt, | ||
| updatedAt: new Date().toISOString(), | ||
| }); | ||
| await this.persistStepOutput(runId, step.name, output); | ||
| this.emit({ type: 'step:completed', runId, stepName: step.name, output }); | ||
| return; | ||
| } |
There was a problem hiding this comment.
🔴 API-mode agents completely bypass the retry loop
The API-mode agent path (cli === 'api') at packages/sdk/src/workflows/runner.ts:3225 returns early before the retry for loop at line 3316. This means step.retries, specialistDef.constraints?.retries, and errorHandling?.maxRetries are all silently ignored for API-mode agents. Any transient failure (rate limits, network errors) causes immediate step failure, even when the workflow is configured with retry policies. This is particularly problematic because LLM API calls are commonly rate-limited and the workflow's default error handling config (builder.ts:357-361) defaults to strategy: 'retry', maxRetries: 2.
Was this helpful? React with 👍 or 👎 to provide feedback.
Wraps executeApiStep in try/catch so failures properly: - Update step DB record to 'failed' with error message - Emit step:failed event - Post failure to channel - Re-throw so workflow DAG handles it correctly Previously, API errors left the step stuck in 'running' state.
1. Pass specialistDef.constraints.maxTokens through to executeApiStep as defaultMaxTokens (was silently ignored). 2. Google API: use x-goog-api-key header instead of URL query param. Prevents key leakage in server logs, proxies, and error messages.
Throws early with clear error instead of returning undefined cmd. Also checks binaries.length for safety.
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Summary
Major SDK update that adds cloud workflow execution, a direct API executor for LLM calls, and migrates the Communicate SDK to the v2 REST/WebSocket protocol.
Cloud Workflow Execution
cloud-runner.ts— Submit workflows to AgentWorkforce Cloud API and poll for completion. Enabled via.run({ cloud: true })on the workflow builder.CloudRunOptions— Configurable API URL, auth token, env secrets forwarding, poll interval, and status change callbacks.WorkflowBuilder.run()now acceptscloud,cloudApiUrl,cloudApiToken,envSecrets,cloudPollIntervalMs, andonCloudStatusChangeoptions.API Executor (cli:
api)api-executor.ts— Direct LLM API calls via fetch (Anthropic, OpenAI, Google) without spawning CLI processes or sandboxes.AgentClivalue:"api"— Agents withcli: "api"execute steps via direct API calls instead of PTY/subprocess.claude-*→ Anthropic,gpt-*/o1-*/o3-*/o4-*→ OpenAI,gemini-*→ Google).skillsfield on agent definitions passes system prompts to API-mode agents.executeAgentStepdetectscli: "api"and routes throughexecuteApiStepinstead of the CLI spawn path.Communicate SDK v2 Protocol Migration
Migrated all HTTP endpoints and WebSocket paths to the v2 protocol:
POST /v1/agentsPOST /v1/agents/registerPOST /v1/agents/disconnectDELETE /v1/agents/{id}POST /v1/dmPOST /v1/messages/dmPOST /v1/channels/{ch}/messagesPOST /v1/messages/channelPOST /v1/messages/{id}/repliesPOST /v1/messages/replyGET /v1/inboxGET /v1/inbox/{agentId}/v1/ws?token=.../v1/ws/{agentId}?token=...Auth simplification: Removed per-agent token auth (
sendHttpAsAgent). All endpoints now use workspace API key auth. Agent identity is passed in request bodies (fromfield) and URL paths.Message parsing simplification: Removed multi-format message extraction (nested
.data,.messagewrappers, multiple event types). Now expects flat response shapes ({ message_id },{ messages },{ agents }).WebSocket events: Simplified from multiple event types (
message.created,dm.received,direct_message.received,thread.reply,group_dm.received) to singlemessagetype.Channel Management
channel-management.test.ts,relay-channel-ops.test.ts) — subscribe, unsubscribe, mute, unmute protocol messages and state updates.tests/integration/broker/channel-management.test.ts) — Full broker flow: spawn agent → subscribe → mute → verify no delivery → unmute → verify delivery → unsubscribe.Other Changes
nonInteractiveArgsfor Codex now includes--dangerously-bypass-approvals-and-sandboxin the command args (not just as metadata).cleanup()method fromonPiRelayreturn type.onRelay/withRelayauto-detect — New unified entry point that auto-detects Pi vs Claude SDK framework from config shape.envSecretsplumbed throughWorkflowRunnerOptions→WorkflowRunner→executeApiStep.Test Plan
AgentRelaychannel operations (subscribe, mute, unmute)buildNonInteractiveCommandtest for Codex bypass flag