agent.send(input, ctx).
defineAgent
Use this for direct Agent integration:
defineAgent always has Agent.kind: "direct". That is an internal discriminator; you do not declare it. t has no capability that must be declared to unlock it. Filesystem assertions such as t.sandbox exist only on an Agent constructed by defineSandboxAgent, whose kind is "sandbox". Everything else is determined by the events that send actually returns and by use of ctx.session; see the Capabilities reference. The complete field set appears below in Agent and Adapter Context fields.
Direct Agent example
input (TurnInput)
string
The text supplied to the current
t.send(...).readonly InputFile[] | undefined
Files attached to this turn, such as images. An Adapter that does not support multimodal input can ignore them.
readonly InputResponse[] | undefined
Present only on response turns (
t.respond / t.respondAll): structured responses for each request, matched by requestId.defineSandboxAgent
Use this for a coding-Agent CLI. The resulting Agent.kind is always "sandbox". Filesystem assertions such as t.sandbox and t.sandbox.fileChanged() are available only for this kind of Agent. The complete field set appears below under SandboxAgentDef in Agent and Adapter Context fields. The complete methods on ctx.sandbox—the Sandbox interface—appear further below under Sandbox interface.
Register it
Agent and Adapter Context fields
The construction parameters fordefineAgent (DirectAgentDef) and defineSandboxAgent (SandboxAgentDef), plus ctx (AgentContext) received by both send(input, ctx) functions:
DirectAgentDef
name
Agent.name unchanged. It is not a registry lookup key; it is used only for display, result attribution, and deduplication fingerprints.
evidenceCoverage
completeEvidenceCoverage for complete collection.
setup
tracing
spanMapper
send
classifySendFailure
Agent.classifySendFailure.
teardown
finally if and only if this Attempt reached the setup point. A setup throw does not exempt it.
SandboxAgentDef
name
Agent.name unchanged. It is not a registry lookup key; it is used only for display, result attribution, and deduplication fingerprints.
evidenceCoverage
completeEvidenceCoverage for complete collection.
ensure
installers
agent.ensure. The factory normalizes omission to an empty array.
setup
config.toml, authentication configuration, and stable run configuration such as model/base/auth for this Attempt. CLI probing, installation, and rechecking belong to agent.ensure. The Runner calls it once after the Sandbox is ready—after layer prepare/ensure/baseline—and before the first send. It returns no value.
tracing
spanMapper
send
classifySendFailure
Agent.classifySendFailure.
teardown
finally if and only if this Attempt reached the setup point. A setup throw does not exempt it.
AgentContext
signal
src/runner/attempt.ts. An Adapter can check it selectively or pass it directly to fetch to exit gracefully early, but it is not the only hard boundary. Even when an Adapter ignores it completely, the Runner uses Effect.timeoutTo as a backstop to force cleanup, including stopping a Sandbox container.
model
model field. A Sandbox Agent typically writes it to configuration during setup; a Direct Agent typically chooses a model with it during send.
reasoningEffort
model: the Experiment decides it, and omission does not override the Agent’s native default.
flags
flags field passes through unchanged. Its contents and shape are entirely defined by the Experiment author, such as { webResearch: true } or { systemPrompt: "..." }. An Adapter reads fields according to its own convention; the framework neither interprets nor validates them. The name intentionally avoids the CLI-parsed flag, which represents how the run operates, such as --timeout / --budget; the two concepts are unrelated.
experimentId
runWho / AgentRun.experimentId. It is undefined when a run does not use an Experiment, such as an AgentRun constructed directly outside the CLI. Typical uses include a SandboxLayer command isolating cross-Attempt infrastructure by Experiment, or an Adapter selecting authentication or routing by Experiment. It is a separate dimension from flags, which holds concrete Experiment-condition values: this is only a stable identifier for which Experiment runs, not its conditions.
evalId
AgentContext directly can omit it. An Adapter can use it to locate read-only host assets beside the task, but cannot use it to bypass isolation of hidden Sandbox criteria.
evalGroup
attempt
session
telemetry
tracing block or Config telemetry. It provides OTLP-trace receiving information for this run: the endpoint plus environment variables for environment-based export. The Agent’s tracing block declares how to give it to a CLI. For environment-based export, spread ctx.telemetry.env into send. For file-based export, write configuration in tracing.configure. For remote HTTP integration, send only needs to spread headers into the request headers, with one new traceparent per turn. The endpoint is startup configuration fixed by defineConfig({ telemetry: { port } }), not passed from here.
progress
agent / ci do not print every update, and it does not enter final results. Do not call it for every token or delta. The Runner attributes the call to the current lifecycle phase—agent.setup, agent.run, or agent.teardown—so callers cannot impersonate another phase. See docs/feature/experiments/library.md.
diagnostic
dedupeKey deduplicates it. Even level: "error" does not change Turn.status or a Verdict. Throw when execution cannot continue.
log
progress({ message: msg }), not a second channel. See Attempt phases in docs/feature/experiments/cli.md. When timeout fails, the most recent lines join the result’s error information to help locate the step that stalled.
ctx.session (AgentSession) is a state slot for one session line. Every send on the same session line receives the same ctx.session. A new session line—the first turn of an Eval or after t.newSession()—receives a fresh one. Its accessors are:
id?: string/capture(id): void: use these for session continuation when the service remembers history.idis the session ID recorded for this line, orundefinedfor a new line.capturerecords the returned ID only when none has been recorded.createSessionSlot<T>(name): creates a typed slot in Adapter module scope. Slots are isolated by symbol identity.get(slot)/set(slot, value): get and set client history or Adapter-private state.take(slot): reads and removes a HITL paused-turn state for one-time consumption.
Sandbox interface
For a Sandbox Agent,ctx.sandbox (Sandbox) is the handle for the current isolated environment. Sandbox extends SandboxOperations and SandboxTransferOperations; the members below are grouped by their declaring interface. CommandOptions are optional parameters for runCommand / runShell:
SandboxOperations
workdir
cwd and targetDir also use it.
runCommand
args are separate argv values and are not interpreted by a shell, so no &&, pipes, or glob expansion occurs. Prefer it for one executable, externally supplied arguments, or input that must avoid shell injection.
runShell
&&, pipes, $(), redirects, and similar shell syntax. Use it when you need to compose commands or branch on conditions.
runCommandOrThrow
runCommand, but throws SandboxCommandExitError on a nonzero exit. Its message contains a bounded, cleaned, redacted stderr tail, falling back to stdout when stderr is empty. The complete output remains in the error’s result; a successful result has exitCode: 0 at the type level.
runShellOrThrow
runShell, but throws SandboxCommandExitError on a nonzero exit. Its error summary, complete output, and successful-result semantics match runCommandOrThrow.
readText
writeText
readBytes
Buffer.
writeBytes
pathExists
SandboxTransferOperations
upload
uploadFile
uploadDirectory
downloadFile
downloadDirectory
Sandbox
stop
sandboxId
otlpHost
string: the Sandbox can reach the host receiver through this hostname.null: the Provider does not promise host callback access. The Runner tries to start an Attempt-scoped receiver inside the Sandbox. This does not guarantee tracing succeeds; when the image lacks the receiver runtime, NiceEval records only a supplemental diagnostic.
defineConfig({ telemetry: { host } }) can explicitly override it after the author provides a controlled tunnel.
appendLog
docker logs and the Docker UI Logs tab can show Agent activity turn by turn. The docker Provider implements it; other Providers can omit it.
CommandOptions
sensitiveValues
env
PATH is Sandbox-managed: each Provider retains the PATH it computed and does not guarantee this option can override it. To extend PATH, use the Sandbox factory’s pathPrepend; see PATH: managed variable and pathPrepend in docs/feature/sandbox/library.md.
cwd
Sandbox.workdir. A relative path resolves from workdir, and an absolute path is used unchanged.
stream
docker logs and the Docker UI Logs tab show it live. Enable it for Agent commands such as codex exec, bub run, or claude to see the Agent’s raw output in container logs. Each Provider implements it differently: docker tees to a file tailed by PID 1, while an unsupported Provider ignores it. How logs surface is the Provider’s concern; the Adapter only declares intent.
onStdout
CommandResult. When a Provider cannot truly stream, it must at least call once with complete stdout after the command ends; it cannot silently drop it.
onStderr
onStdout; complete stderr remains in CommandResult.
user
USER, Compose service user:, or E2B template default user. See Execution identity in docs/feature/sandbox/library.md.
The semantics are consistent across Providers, while each maps it to its native mechanism: Docker uses exec --user; E2B uses { user }; Vercel accepts only "root" and maps it to { sudo: true }, with other values erroring. A Provider that is root for the whole lifetime treats it as a no-op. A Provider that cannot change identity at all can reject it, but omission and an explicit value keep the same semantics across Providers.
timeoutMs
docs/feature/sandbox/architecture.md. The Provider layer has no independent default. An explicitly shorter value is an intentional declaration and applies normally; when it expires, the attribution is command-explicit timeout.
signal
ctx and t
ctx is the runtime context an Adapter sees. t is the test context an Eval author sees. They use the same runtime data, but have different responsibilities.