Pre-release Harn is pre-1.0 — the language, standard library, and CLI may change between releases. See the release notes

Named session inputs

Named inputs let a host give an agent credentials without putting their values in model context. Secrets expose names and usage policies. Ordinary variables also expose their values. Inputs belong to one live session and are excluded from durable conversation state.

Private control interface#

An authenticated ACP client calls session/inputs with a sessionId and one command. The command is one of these shapes:

{"kind":"list"}
{
  "kind": "put",
  "spec": {
    "name": "SERVICE_KEY",
    "kind": "secret",
    "lifetime": {"kind":"session"},
    "usage": {"kind":"websites","origins":["https://api.example.com"]}
  },
  "value": "private input from the host",
  "replace": false
}
{"kind":"remove","name":"SERVICE_KEY"}

For a host that owns a conversation across several execution sessions, sync installs an atomic private snapshot: {kind: "sync", snapshot: {sourceId, revision, inputs: [{spec, value}], redactions: []}}. Produce it with SessionInputs::write_private_snapshot; pass a random stable identifier for that host's conversation. It includes the host's current grants and retired secret values needed to filter late output. The runtime refuses older revisions for that source and treats an identical revision as already applied. A snapshot replaces only grants belonging to that source. Preconfigured inputs and grants from other sources survive. A name collision with another source is refused atomically. Source history is limited to 256 sources per session. Its response reports applied and descriptions. Snapshots are private control messages and must never enter traces, transcripts, or saved launch documents.

The put request is a private control message, never a tool argument or a transcript message. Hosts must keep it out of request logging. Successful responses contain descriptions or removal outcomes, never secret values. The interface remains available while a prompt waits for input.

The HTTP API exposes the same commands at POST /v1/sessions/{session_id}/inputs. Its body is the command object, without the ACP envelope. It uses the existing API authentication and session checks. Private commands bypass task storage and event publication. Remote clients must use authenticated HTTPS and refuse redirects before submitting values.

Names follow portable environment syntax and are case-sensitive. A name is unique across both kinds. variable permits an empty value; secret does not. lifetime defaults to session. until adds an absolute unix_ms expiry. saved records that the host has separately saved the value in its secure store; Harn still discards its live grant on session close. Harn does not silently persist a value because its description says saved.

usage defaults to session_tools. websites accepts exact HTTPS origins and disables command use. Paths, URL credentials, queries, fragments, wildcard hosts, and non-HTTPS origins are refused. Hosts that accept domain names in a form must turn them into HTTPS origins before submitting them. Website limits require the host's normal HTTPS trust and proxy settings. Requests with custom proxy or TLS options cannot use website-restricted inputs, including options inherited from an HTTP session.

The shared implementation bounds a session to 256 inputs, 64 KiB per value, and 1 MiB of retained private material. Removed and replaced secrets remain in the bounded output-filtering set until the owner is dropped.

Harn interface#

harness.secrets.inputs() lists descriptions. Each contains name, kind, lifetime, and usage. Only ordinary variables have a value field. harness.secrets.remove_input(name) removes a live grant and returns whether one existed. Neither method reads or changes a saved credential.

Bounded harness.net requests accept secret_headers, a map of HTTP header names to {name, prefix?} bindings. Harn resolves the named value privately, checks its final destination, and marks the HTTP header sensitive. Such requests never follow redirects or retry automatically. Downloads and streams refuse these bindings because their output can bypass the bounded result.

The canonical harness.tools.run_command interface accepts input_env, a map of process environment names to session input names. Only declared bindings reach the child. A binding cannot also appear in env or env_remove. Commands with input bindings require foreground execution and pipe capture. They retain the existing command policy, sandbox, timeout, and cancellation path. Website-restricted inputs fail before a process starts.

Host embedding#

harn_execution_policy::session_inputs::SessionInputs owns validation, expiry, restriction checks, zeroizing private storage, and descriptions without a VM dependency. Native hosts can project that same implementation through their foreign-function interface. write_private_snapshot is for private transport only, never model tool output.

harn_vm::session_inputs binds custody to the existing isolated session runtime, so normal task migration preserves access and independent runtimes do not share secrets. Forks and restored sessions receive no grants unless their host explicitly installs them.

Hosted job runners pass a private snapshot through JobRunOptions::with_session_inputs. The runner installs it after resetting the job runtime and closes its isolated session when the job finishes. The snapshot is separate from the job event and result. A later job receives no inputs unless its host explicitly supplies another snapshot.

Protection limits#

Exact secret values are filtered from normal HTTP results, command output artifacts, model-facing request text, and the existing operational redaction path. Removed and replaced values remain covered for late output. This complements pattern-based redaction; it does not depend on a recognizable token prefix.

A program given a secret can transform it, write it elsewhere, or send it to another server. Output filtering cannot prevent arbitrary transformations. Use website restrictions when a secret must stay within selected destinations; Harn then refuses all command bindings for that input. Restrictions cannot recall a request or revoke a value already held by a running process.