DSH plugin PTC runtime: timeouts, cancellation and sandbox
The PTC runtime is not “run some code”; it is “run a program in an execution world with host bindings, a budget, and reported sandbox facts”. ctx.ptcRuntime has two actions: resolve(request) fills caller input into a complete PtcRunSpec, and run(spec) executes it and returns a PtcRunResult. Program failure is a field on the result, not an exception; sandbox facts are reports, not proof.
DeepSeek Harness: Three core objects
Separate request, spec, and result so validation and execution do not blur together. The relationship:(source)
| Object | Produced by | Key fields |
|---|---|---|
PtcRunRequest | Caller | program, bindings, timeoutMs, sandboxPolicy, signal |
PtcRunSpec | Provider resolve | resolved cwd, timeoutMs, and supported choices |
PtcRunResult | Provider run | value, logs, error, sandbox |
resolve validates supported choices and applies deployment defaults. Omitting timeout uses the provider default, a numeric request is capped, and null requests no deadline. Providers reject unsupported choices before execution instead of failing mid-run.
run receives complete input: cwd exists and timeoutMs is either positive or null. Implementations do not repeat default resolution on every execution.
DeepSeek Harness: Designing bindings
Bindings are host functions exposed to the program, not an arbitrary object channel; arguments and return values must be lossless JSON. Design points:(source)
- One global per namespace — each
PtcBindingNamespaceis exposed underglobal, with functions below it. Expected: the program calls them like normal async functions. - Portable names only —
[A-Za-z_][A-Za-z0-9_]*, not a reserved word. Expected: the same namespace list works on JS and Python backends. - Own properties, even for odd names —
__proto__andconstructorare ordinary keys, constructed with a null prototype. Expected: no prototype collision. - Optional typed errors — an
errorClasslets the program see a real error constructor and member name. Expected: rejections are structured. - Lossless values — arguments and resolutions cross a JSON boundary without loss. Expected: non-cloneable values fail explicitly instead of becoming strings.
If a binding needs a complex object, split it into JSON-expressible fields; do not rely on a backend’s serializer happening to accept it.
DeepSeek Harness: Failure taxonomy and result handling
PTC failures are orthogonal outcomes: a timeout is not an exception, an abort is not a timeout, and a substrate death is neither. Eight kinds:(source)
exception— the program threw or failed to parse/transform.timeout— an implementation-owned budget expired.abort— the request signal fired.worker-exit— the execution substrate died, such as OOM.invalid-output— the completion value was not lossless JSON.output-limit— serialized logs, value, or diagnostics exceeded a cap.protocol— invalid or over-budget control traffic.sandbox-unavailable— required confinement could not be established.
Do not rethrow error as an exception; it is the field the caller renders or feeds back to the model. Logs are plain strings; each channel preserves its own order, while interleaving across channels is backend-dependent.
DeepSeek Harness: Three integration options
You do not have to write a runtime to use PTC; choose by isolation and persistence needs. Three options:(source)
- Use the published Node provider — best for most local execution, with sandbox and persistent REPL behavior. Expected: no custom process isolation.
- Implement a stateless provider — a fresh environment per request, ignoring
stateOwner. Expected: simple, good for one-shot computation. - Implement a retained-state provider — isolate memory by
stateOwnerand callrelease(owner)when the owner ends. Expected: reuse within one owner, but retained objects never enter the persistent session format.
Every implementation terminates and awaits active executions during disposal. Cleanup failure should reject release or shutdown.
DeepSeek Harness: Security boundaries
Sandbox facts are reports, not guarantees; a successful program does not prove every restriction was enforced. Four points:(source)
- Read
sandbox.modeanddenied— mode, observed denial, and enforcement completeness are independent facts. Expected: no “no error” conclusion about privilege. isolationis not a security claim — it describes the substrate. Expected: do not use it as compliance evidence.- No proxy configuration — Workflow workers and the Node PTC process do not inherit proxy variables. Expected: model scripts cannot read a proxy URL with credentials; direct egress must configure its own proxy and stay inside the sandbox.
- Distinguish program failure from contract misuse — program failure is in
error; only Service Definition misuse rejects. Expected: user code errors are not reported as framework crashes.
DeepSeek Harness: A minimal call skeleton
The caller only needs resolve and run; program failure is read from result.error. Skeleton:(source)
const spec = ctx.ptcRuntime.resolve({
program,
bindings: [{ global: 'tools', functions: { readFile } }],
cwd,
timeoutMs: 30_000,
})
const result = await ctx.ptcRuntime.run(spec)
if (result.error) return { ok: false, kind: result.error.kind }
return { ok: true, value: result.value, logs: result.logs }
resolve may throw for an unsupported choice; that is a caller contract error. A program failure inside run is result.error; do not mix the two.
Implementation checklist
Before writing run, settle four decisions or the implementation will churn on error handling and state leaks. Checklist:
- Language and programFormat — async function body or REPL, which decides top-level
awaitandreturn. Expected: programs do not fail at parse time for the wrong format. - Binding namespaces — which host functions, which global names, and whether typed errors are needed. Expected: names follow the portable identifier rule.
- Budget and isolation — default timeout, numeric cap, meaning of
null, and whether sandboxing exists. Expected:resolvecan produce a completePtcRunSpec. - Resource release — how each run’s state is isolated and how
release(owner)terminates active execution. Expected: cleanup failure rejects explicitly.
DeepSeek Harness FAQ
How is PTC different from a normal tool call? A tool call is one function invocation. PTC lets the model write a program that composes multiple calls against host bindings while sharing one execution’s directory, budget, and sandbox facts.
Can a PTC program persist state?
stateOwner retains state inside the process, but it is not part of the persistent session format; state does not survive process exit.
What happens to in-flight binding calls after a timeout? The runtime stops the program, but the caller owns settlement of in-flight binding calls. Do not treat timeout as “all side effects stopped”.
The short version: keep validation, execution, result, and sandbox separate; mixing them is how program failures get misreported as framework crashes.
FAQ
DeepSeek Harness: PTC runtime is an optional capability seam provided by dsh-ptc-runtime. ctx.ptcRuntime runs a program against host bindings and reports output, failures, and applicable sandbox facts. It is not part of the core agent loop.
DeepSeek Harness: ptcRunRequest is the caller input with program, bindings, cancellation, and optional execution choices. resolve validates supported choices and supplies cwd, deadline, and authority to produce a PtcRunSpec; run accepts only the complete spec.
DeepSeek Harness: no. Program failure is returned in PtcRunResult.error. Only Service Definition contract misuse rejects. Failure kinds include exception, timeout, abort, worker-exit, invalid-output, output-limit, protocol, and sandbox-unavailable.
DeepSeek Harness: no. Binding arguments and return values must be lossless JSON. The runtime rejects values that would lose information or cannot be cloned rather than silently converting them. Each backend also has its own transport limits.
DeepSeek Harness: the official docs say Workflow workers and the Node ptc-runtime process do not receive proxy configuration, so model-written scripts cannot read a proxy URL that may contain a password. Direct requests must configure their own proxy and remain subject to the sandbox.
Related Terms
- PTC
- PTC is the DeepSeek Harness capability that lets a model write a program and call host bindings. It is provided by the optional ctx.ptcRuntime seam and is not part of the core agent loop.— DeepSeek Harness reference - PTC runtime
- PtcRunRequest
- PtcRunRequest is the caller input for one PTC execution, containing program, bindings, cwd, timeoutMs, sandboxPolicy, stateOwner, and signal. resolve validates and fills defaults.— DeepSeek Harness reference - PTC runtime
- PtcRunResult
- PtcRunResult is the outcome of one PTC execution, containing optional sandbox facts, a completion value, captured logs, and an error field. Program failure does not reject run().— DeepSeek Harness reference - PTC runtime
- stateOwner
- stateOwner is an in-process object identity for optional retained memory in a PTC request. Distinct objects are isolated; omitting it requests a fresh environment, and consumers call release(owner) when done.— DeepSeek Harness reference - PTC runtime
Sources
- DeepSeek Harness reference - PTC runtime· deepseek-ai
- DeepSeek Harness docs - Network proxy· deepseek-ai