feat(sdk): add ProcessBackend workflow for cloud sandbox execution#747
Conversation
Adds ProcessBackend + ProcessEnvironment interfaces to the SDK and accepts processBackend in WorkflowRunnerOptions. Relay-side counterpart to AgentWorkforce/cloud#115. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 787ef38a2a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| command: 'git add packages/sdk/src/workflows/types.ts packages/sdk/src/workflows/runner.ts && git diff --cached --quiet && echo "NO CHANGES" && exit 1; git commit -m "feat(sdk): add ProcessBackend interface and accept in WorkflowRunnerOptions" && git push origin feat/process-backend-runner', | ||
| captureOutput: true, |
There was a problem hiding this comment.
Switch to feat branch before committing and pushing
In workflows/wire-process-backend.ts (checked the commit/open-pr steps), the script never creates or checks out feat/process-backend-runner before running git commit, but then pushes and opens a PR from that fixed branch name. When this workflow is run from another branch (e.g., main), the new commit is created on the current branch and either git push origin feat/process-backend-runner fails because the local ref does not exist, or it pushes an older unrelated local branch with that name, producing a PR without the new changes.
Useful? React with 👍 / 👎.
xkonjin
left a comment
There was a problem hiding this comment.
Code review — ProcessBackend wiring workflow
This is a workflow script that generates a PR, not a runtime change, so the risk surface is low. A few things worth tightening before it lands:
-
Shell escaping in the workflow script — the generated uses a hand-rolled regex to decide when to quote args. That's fragile for args containing spaces, unicode, or pipes. Prefer or a proper shell-escape helper, or pass and as an array to if the backend supports it.
-
Timeout math — can round a 500ms timeout up to 1s, which is fine, but document that the backend's is ceil-rounded from milliseconds.
-
Missing usage — the task narrative mentions as part of the interface but the workflow executor never calls it. If agent steps need file assets (e.g. context bundles), consider where fits in .
-
Broker still required? — the workflow itself disables the fork change (). Make sure the final PR description is crystal clear that is accepted but not yet wired into execution.
Nothing blocking, just polish.
xkonjin
left a comment
There was a problem hiding this comment.
Code review — ProcessBackend wiring workflow
This is a workflow script that generates a PR, not a runtime change, so the risk surface is low. A few things worth tightening before it lands:
-
Shell escaping in the workflow script — the generated
commanduses a hand-rolled regex/^[a-zA-Z0-9._\\-\\/=]+$/to decide when to quote args. That's fragile for args containing spaces, unicode, or pipes. PreferJSON.stringify(arg).slice(1, -1)or a proper shell-escape helper, or passcmdandargsas an array toenv.execif the backend supports it. -
Timeout math —
Math.max(1, Math.ceil(timeoutMs / 1000))can round a 500ms timeout up to 1s, which is fine, but document that the backend'stimeoutSecondsis ceil-rounded from milliseconds. -
Missing
uploadFileusage — the task narrative mentionsuploadFileas part of the interface but the workflow executor never calls it. If agent steps need file assets (e.g. context bundles), consider whereuploadFilefits inexecuteAgentStep. -
Broker still required? — the workflow itself disables the fork change (
DO NOT change the fork at line 4038). Make sure the final PR description is crystal clear thatprocessBackendis accepted but not yet wired into execution.
Nothing blocking, just polish.
…ts pass The fix-failures agent step always spawned Claude even when build+tests passed, causing 3 timeout retries. Now build/test steps use failOnError:true and gate commit directly. Also makes open-pr idempotent (skips if PR exists). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The runner now synthesizes a RunnerStepExecutor from processBackend when no explicit executor is supplied, so every existing executor.executeAgentStep() call site flows through processBackend.createEnvironment().exec() without further plumbing. Adds: - process-backend-executor.ts adapter (buildCommand → env.exec, with cwd/env/timeout propagation and env.destroy() in finally) - unit tests covering the happy path, non-zero exit, cli:"api" rejection, and deterministic-step pass-through - index export for createProcessBackendExecutor Replaces the "stored but unused" TODO in runner.ts:4052 with a pointer to the adapter. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses PR #747 feedback: - executeAgentStep was baking env vars into the command as a shell prefix and never forwarding agentDef.cwd. Structured backends (process-backend implementations that configure subprocess env/cwd from execOpts) would therefore miss auth env and run commands in the wrong directory. Drop the shell-prefix path and pass both env and cwd through execOpts, matching executeDeterministicStep. - Test mocks were declared with vi.fn(async () => ...) which infers an empty-tuple call signature, so exec.mock.calls[0] typed as []. Fix by typing mocks as vi.fn<ProcessEnvironment['exec']>(...). This resolves every CI failure on the PR (SDK typecheck, SDK build, Test, E2E, Package Validation, Clean-Room, Workers Safety, Workflow Validation) — all cascaded from the same TS2493/TS2339. - Add a test that asserts env is *not* baked into the command and that agentDef.cwd flows through execOpts.
Summary
Adds
ProcessBackendandProcessEnvironmentinterfaces to the SDK, acceptsprocessBackendinWorkflowRunnerOptions, and creates a ProcessBackend-backedRunnerStepExecutorwhen no explicit executor is provided.What changed
ProcessBackendandProcessEnvironmentfrom@agent-relay/sdk/workflowsWorkflowRunnerOptionsaccepts an optionalprocessBackendProcessEnvironment.execenv,cwd, and ceil-roundedtimeoutSecondsare passed through structured exec optionsRelayCast.createWorkspace()API-key handling now guards the optionalapiKeyshape from the latest@relaycast/sdktypesBoundary
createEnvironment()exec(command, opts)destroy()uploadFile()remains part of the interface for future file asset staging and is not called by the current executor.PR feedback addressed
feat/process-backend-runnerbefore committing and pushes that branch explicitlyenvandcwdbehaviorTest plan
npm --prefix packages/sdk run buildnpm run build:packagesnpm run buildnpx vitest run --config vitest.config.ts src/workflows/__tests__/process-backend-executor.test.tsfrompackages/sdk