feat(agents-api): add Tenki sandbox provider for function tool execution#3468
Open
buffgbob wants to merge 1 commit into
Open
feat(agents-api): add Tenki sandbox provider for function tool execution#3468buffgbob wants to merge 1 commit into
buffgbob wants to merge 1 commit into
Conversation
Adds @tenkicloud/sandbox-backed TenkiSandboxExecutor mirroring the
Vercel provider: pooled microVM sessions keyed by dependency hash,
per-run directory isolation, and cleanup on session end. Configure via
sandboxConfig { provider: 'tenki' } or SANDBOX_TENKI_API_KEY, with
optional SANDBOX_TENKI_BASE_URL / SANDBOX_TENKI_PROJECT_ID; the project
is auto-discovered via whoAmI() when not configured.
Command timeouts are enforced client-side (the SDK's exec timeoutMs is
not enforced in 0.3.x): on expiry the process is killed, termination is
awaited for a bounded grace period, and the timed-out session is
retired by identity. Pool entries track active leases so TTL/max-use
expiry defers close() until in-flight executions finish, sessions only
enter the pool after dependency install completes, pool expiry follows
the session's server-side timeoutAt deadline, deferred closes are
tracked and awaited by cleanup() alongside in-flight initializations so
no session can leak past shutdown, and executors are cached per full
configuration hash.
🦋 Changeset detectedLatest commit: 56d4e5f The changes in this PR will be included in the next version bump. This PR includes changesets to release 10 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
buffgbob
requested a deployment
to
inkeep-oss-sync
July 17, 2026 13:49 — with
GitHub Actions
Waiting
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.
feat(agents-api): add Tenki sandbox provider for function tool execution
Summary
Adds Tenki Sandbox as a third sandbox provider for function tools, alongside the existing
nativeandvercelproviders. Tenki is a hosted microVM sandbox service, so this gives deployments strong isolation for function tool execution from any environment (including ones where child-process spawning is restricted) without operating their own sandbox infrastructure.Changes
TenkiSandboxExecutor(agents-api/src/domains/run/tools/TenkiSandboxExecutor.ts) — new executor using@tenkicloud/sandbox, mirroringVercelSandboxExecutor: sessions are pooled and reused per dependency hash, honoring the existingFUNCTION_TOOL_SANDBOX_POOL_TTL_MS/FUNCTION_TOOL_SANDBOX_MAX_USE_COUNTlimits; each invocation writes its wrapper to an isolated/home/tenki/runs/<runId>/directory and cleans it up afterwardsSandboxExecutorFactory— routesprovider: 'tenki'to the new executorTenkiSandboxConfigadded to theSandboxConfigunion inagents-api/src/types/app.tsanddomains/run/types/executionContext.ts(authToken,baseUrl, andprojectIdoptional; the SDK falls back toTENKI_AUTH_TOKEN/TENKI_API_KEYenv vars, and the project is auto-discovered viawhoAmI()when not configured)SANDBOX_TENKI_API_KEY(+ optionalSANDBOX_TENKI_BASE_URL,SANDBOX_TENKI_PROJECT_ID) selects the Tenki provider inagents-api/src/index.ts, after the existing Vercel env check so current behavior is unchanged'tenki'added to the provider enum in/capabilitiesand the manage-ui capabilities typeTenkiSandboxExecutor.concurrency.test.tsmirrors the Vercel concurrency test (single create under concurrent invocations, per-run file isolation) and additionally asserts outbound networking, project auto-discovery, and dependency installfunction-tools.mdxwith a config example@inkeep/agents-apiImplementation notes
A note on scope: the executor follows
VercelSandboxExecutor's structure (dependency-hash pooling, per-run directories, the same TTL/max-use limits) but is deliberately stricter about session lifecycle — leases, deferred closes, and shutdown draining. Tenki sessions are billed cloud microVMs rather than local processes, so "a command was cut short at the TTL boundary" and "a session outlived cleanup()" are user-visible bugs here in a way they aren't for local providers; each behavior below exists because a test demonstrated the failure. Happy to split any of this out or simplify if you'd rather keep provider parity — and some of it (the mid-install pool-publish race, the 2-second reuse window) may be worth porting to the Vercel executor as a follow-up.allowOutbound: truesonpm installof tool dependencies works (matching Vercel sandbox behavior, which always has egress).Session.exec()types atimeoutMsoption but does not enforce it in 0.3.x, andkill()only enqueues the signal. A timed-out sandbox is retired from the pool rather than reused, since surviving child processes cannot be ruled out.maxDurationMs = pool TTL + command timeout + buffer, and pool expiry is computed from the session's actual server-side deadline (session.timeoutAt— the clock starts at creation, so cold-start/install time is accounted for). The pool only hands out sessions that still have a full command timeout of life remaining, so a pooled call can never be cut short by session expiry.close()until its last in-flight execution finishes, and sandboxes only enter the pool after dependency install completes so a concurrent call can never lease a half-initialized session.cleanup()is shutdown-safe: it awaits in-flight sandbox initializations before draining the pool, an initialization that completes after shutdown begins closes its session instead of publishing it, and deferred/asynchronous closes started by lease release or retirement are tracked and awaited — no cloud session can outlive the executor.projectIdisn't configured, the executor resolves it once viawhoAmI()(using the sole accessible project, erroring if there are several) — the same auto-selection the Tenki CLI performs at login.^0.3.6rather than the just-released0.4.0to satisfy this repo'sminimumReleaseAge(3-day supply-chain cooldown). The API surface used here is identical in both versions.Testing
TenkiSandboxExecutor.concurrency.test.ts(SDK mocked) — concurrent invocations create one sandbox with unique per-run paths; sandbox created withallowOutbound, correctcpuCores/maxDurationMs, auto-discoveredprojectId, and dependency install. Existing factory + Vercel executor tests still pass (6/6).pnpm typecheck,pnpm lint(biome),pnpm knipall clean.left-pad): installed inside the sandbox over egress, correct result (~4s cold)executor.cleanup()closed all sessions;tenki sandbox listconfirmed nothing leakedopenapi:update-snapshot, 12/12 tests pass)