Skip to content

feat(tangle-provider): expose maxLifetimeSeconds and idleTimeoutSeconds on environment create — the provider sends neither, so a child that waits is suspended at 30 minutes #309

Description

@drewstone

Versions checked: @tangle-network/agent-provider-tangle 1.1.7 (tag @tangle-network/agent-provider-tangle@1.1.7, 1d4a5a3), @tangle-network/agent-interface 2.6.1, @tangle-network/sandbox 0.37.1 — the Discovery Lab's installed pins, read from node_modules. The provider and interface files cited below are byte-identical on origin/main (9e8e0ad, provider 1.1.8); tangle-contract-safety.ts changed since 1.1.7 but not on lines that matter here.

What the code does

  • packages/agent-provider-tangle/src/tangle-create-options.ts:72-98 — sandboxOptionsFromCreateInput builds the CreateSandboxOptions that tangle-provider.ts:123-145 hands to client.create. It maps environment, cwd, git, resources, env, secrets, egress, billing owner, metadata, name, idempotency key, and backend. It sets no maxLifetimeSeconds and no idleTimeoutSeconds.
  • tangle-create-options.ts:187-203 — assertCreateInputShape deletes the known keys and throws Tangle create input contains unsupported fields for anything else; :38-40 refuses a non-empty providerOptions. A caller cannot carry a lifetime through the generic input.
  • packages/agent-interface/src/environment-runtime.ts:824-874 — CreateAgentEnvironmentInput has no lifetime or idle field.
  • The Sandbox SDK accepts both: @tangle-network/sandbox 0.37.1 dist/types-DTDI3kek.d.ts:1517-1549 declares CreateSandboxOptions.maxLifetimeSeconds? and idleTimeoutSeconds?, and documents that create() substitutes no default, so an omitted field falls back to the platform's global hard TTL (365 days) and global idle timeout (30 minutes). The on-chain ABI carries them as well (dist/index-CSC61YaS.d.ts:137-141, max_lifetime_seconds, idle_timeout_seconds).
  • The exact-process path already sends one of them: packages/agent-provider-tangle/src/exact-process.ts:239-247 validates maxLifetimeMs as whole seconds and :281 sends maxLifetimeSeconds: input.maxLifetimeMs / 1_000 (installed dist exact-process.js:161-164, 192). The ordinary environment create, which is what Runtime's supervised provider path uses for children, cannot.
  • The only route today is a private mapCreateInput (tangle-types.ts:675); assertMappedCreateOptions (tangle-create-options.ts:226-267) does not reject lifetime fields, so a custom mapper can inject them. That is the same private-mapper workaround feat(agent-interface): carry egress policy and billing owner on CreateAgentEnvironmentInput #275 removed for egress and billingOwner.

Correction to the findings' wording: the findings say the SDK "exposes them in the ABI only". Checked against the installed 0.37.1 declarations, CreateSandboxOptions exposes both fields; the gap is the provider mapping and the interface input, not the SDK.

Why it matters

From the findings (Discovery #159, rows 6a and 6b), agent-dev-container origin/develop 4ebcfe9eee:

  • apps/orchestrator/src/orchestrator-lifecycle.ts:61-66, 164, 168-175, 905-908, 929-931: LIFECYCLE_IDLE_TIMEOUT_MS 30 min suspends; LIFECYCLE_COLD_TIMEOUT_MS 6 h suspended deletes; hard TTL 1 year; a per-sandbox lifecycle.maxLifetimeMs overrides. Idle means no sidecar request and no live TCP flow (apps/orchestrator/src/lib/sidecar-activity.ts:36-41).
  • apps/orchestrator/src/driver/tangle/index.ts:551-552: the on-chain create sends maxLifetimeSeconds: 0n, idleTimeoutSeconds: 0n (owner: agent-dev-container; not filed here).

A supervised child that holds an open turn is active; a child parked between steers for more than 30 minutes is suspended and deleted 6 hours later, and whether a suspended sandbox resumes transparently under Runtime's SSE reattach is an open unknown in the findings. No Lab run has reached this ceiling yet: the longest direct-path run in the census of 32 is company-frontiers-continuation-20260908-r6 at 1.10 h, and every run settled. The current Lab registrations declare no deadline, so a weeks-long play depends on children that can outlive 30 minutes of quiet, and the installed stack cannot declare that.

Correct behavior

  1. agent-interface: add optional lifetime fields to CreateAgentEnvironmentInput (for example maxLifetimeMs and idleTimeoutMs, matching the exact-process input's maxLifetimeMs at environment-exact-process.ts:127), the way feat(agent-interface): carry egress policy and billing owner on CreateAgentEnvironmentInput #275 added egress and billingOwner.
  2. agent-provider-tangle: accept them in assertCreateInputShape, validate whole seconds as exact-process.ts:239-247 does, and map them to CreateSandboxOptions.maxLifetimeSeconds and idleTimeoutSeconds in sandboxOptionsFromCreateInput. A provider that cannot honor a declared lifetime should fail the create rather than drop the field, the rule the egress mapping already applies (tangle-create-options.ts:102-113).
  3. Runtime's supervised provider path then needs to pass a lifetime for children; today only src/candidate-execution/exact-process-executor.ts:123-135 does (agent-runtime; noted, not filed here).

Findings: https://github.com/tangle-network/discovery/blob/4cbc5406707cdf753e3b950ad0e38cb67914da95/docs/research/159-long-horizon-ceilings.md (rows 6a, 6b, and "Upstream gaps"). Filed for Discovery map tangle-network/discovery#136 through tangle-network/discovery#167.

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions