Repository navigation
fix(platform): run agent connector calls in process, bounded - #4544
Merged
Merged
Conversation
The in-sandbox connectors bridge passed the turn's own session as execSessionId, so each live yaml-js body ran as `node -e <program>` in the agent's session. The program embeds the body's scope as a string literal, credential.secrets included: while the call ran, the org's raw connector key sat on a command line any process of that session (the agent, same uid) could read through /proc/<pid>/cmdline or ps. Each call also paid a Node cold start (~40 ms, ~48 MB), took one of the session's four live-exec places (parallel tool calls then failed with "sandbox produced no result"), and added ~150-250 ms. The bridge now dispatches without a session, so the body runs on the in-process live runner that automation runs and chat already use: the shipped catalog is the only code it runs (organizations cannot upload connector bodies), ctx.http is the same policed live host, and the credential stays in the platform process. The connectors spec states it as CONN-R13, held by the bridge route test. No caller passes execSessionId any more. The session-bound path it reaches (the sandbox-exec runner, engine_exec_runner, portable-live, the hostcall token and route, and the device relay's allowance for that route in the sandbox service) is left in place: removing it spans the platform's engine, routes and env and the sandbox service, which is not a self-contained change.
Moving agent bridge calls onto the in-process live runner lost two bounds the sandbox gave them: four live execs per session, and a kill when a body overran its deadline. In the shared backend process the deadline only released the caller; the body went on calling its vendor, and an agent retrying a slow call (a recursive Drive listing on a large account) started another body each time. Bridge calls also gained ctx.files, so an agent's read of an attachment stored blobs and file records in the organization's store, which the sandbox path never did. - A yaml-js body's host gets a signal that aborts at the body's time limit, so every ctx.http and ctx.files request after it rejects and the body unwinds at its next host call (a test shows 9 vendor requests after the limit without it, none with it). - The bridge runs at most four of a session's calls at once per backend process; a further call gets a busy refusal the agent can retry. - Bridge calls run without a file store, as they always did. - runConnectorAction no longer accepts a session to run a body in; the now unused session-bound machinery is recorded in the contract debt ledger, and comments that described it as live are corrected. CONN-R14 states the bounds; a service-level test holds the runner choice (CONN-R13) with a yaml-js example instead of a native connector.
…t refuses The host signal and the caller's deadline fired on the same tick, so a caller could be told 'request aborted' by the body's next host call instead of the body's time-limit error. Host calls now start refusing 100 ms past the limit.
yannickmonney
force-pushed
the
fix/connector-bridge-in-process
branch
from
October 8, 2026 12:45
9f1380c to
0964095
Compare
codeRunnerForSession lost its last caller when connector bodies moved in process; the program runner beneath it stays with the rest of the session-bound path listed in the contract debt ledger.
…in-process # Conflicts: # services/platform/tests/manual/reference/automation.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An agent's connector call through the sandbox bridge ran the connector's body as
node -e <program>inside the agent's own session, with the organization's connector secrets embedded in the program — readable by the agent (same uid) through/proc/<pid>/cmdlineorpswhile the call ran — plus a Node cold start (~40 ms, ~48 MB) and a runnerd live-exec slot per call.Changes
fix(platform): run agent connector calls in process, not in the sandbox
The in-sandbox connectors bridge passed the turn's own session as
execSessionId, so each live yaml-js body ran as
node -e <program>inthe agent's session. The program embeds the body's scope as a string
literal, credential.secrets included: while the call ran, the org's raw
connector key sat on a command line any process of that session (the
agent, same uid) could read through /proc//cmdline or ps. Each
call also paid a Node cold start (~40 ms, ~48 MB), took one of the
session's four live-exec places (parallel tool calls then failed with
"sandbox produced no result"), and added ~150-250 ms.
The bridge now dispatches without a session, so the body runs on the
in-process live runner that automation runs and chat already use: the
shipped catalog is the only code it runs (organizations cannot upload
connector bodies), ctx.http is the same policed live host, and the
credential stays in the platform process. The connectors spec states it
as CONN-R13, held by the bridge route test.
No caller passes execSessionId any more. The session-bound path it
reaches (the sandbox-exec runner, engine_exec_runner, portable-live,
the hostcall token and route, and the device relay's allowance for that
route in the sandbox service) is left in place: removing it spans the
platform's engine, routes and env and the sandbox service, which is not
a self-contained change.
fix(platform): bound agent connector calls that run in process
Moving agent bridge calls onto the in-process live runner lost two bounds
the sandbox gave them: four live execs per session, and a kill when a
body overran its deadline. In the shared backend process the deadline
only released the caller; the body went on calling its vendor, and an
agent retrying a slow call (a recursive Drive listing on a large account)
started another body each time. Bridge calls also gained ctx.files, so an
agent's read of an attachment stored blobs and file records in the
organization's store, which the sandbox path never did.
limit, so every ctx.http and ctx.files request after it rejects and the
body unwinds at its next host call (a test shows 9 vendor requests
after the limit without it, none with it).
process; a further call gets a busy refusal the agent can retry.
now unused session-bound machinery is recorded in the contract debt
ledger, and comments that described it as live are corrected.
CONN-R14 states the bounds; a service-level test holds the runner choice
(CONN-R13) with a yaml-js example instead of a native connector.
Verification
@tale/platformtypecheck clean; type-aware oxlint clean on the touched files.Part of the sandbox footprint and robustness pass (#4533, #4538 and siblings).