Agent Harness
Harness (a13n-harness) is the embeddable execution SDK behind Harness UI and Service. It builds reusable agents, runs them with current tools and Environments, streams observations, and returns state for continuation. Start with the offline quickstart; the Python import is a13n_harness.
Capability composition
Build an AgentSpec with only the behavior your application needs. For example, to expose Environment tools and working state:
from a13n_harness import AgentSpec, HarnessBuilder
from a13n_harness.capabilities import WorkingStateCapability
from a13n_harness.environment import DynamicEnvironmentCapability, DynamicEnvironmentConfiguration
executable = HarnessBuilder().build(
AgentSpec(model="openai-responses:gpt-5"),
output_type=str,
capabilities=(
DynamicEnvironmentCapability(DynamicEnvironmentConfiguration()),
WorkingStateCapability(),
),
)
Supply a Host-owned EnvironmentSource to each run(..., environment=...), or use environments={...} for named mounts. Harness invokes the source’s readiness preparation on first use, then opens and closes fresh fixed-target executions; your application selects their configuration, current state, access policy, and when to destroy a backing target. See Environments and Capabilities.
Browser tools
Connect to an existing Chromium instance through a trusted CDP endpoint. The application prepares Chromium and its profile; Harness does not install or launch a browser. cdp-use is included in the normal Python dependencies.
from a13n_harness import AgentSpec, HarnessBuilder, RunBindings
from a13n_harness.capabilities import BrowserUseCapability
from a13n_harness.capabilities.browser.scope import CdpBrowserBackend
async def inspect_page(cdp_url: str) -> str:
executable = HarnessBuilder().build(
AgentSpec(model="openai-responses:gpt-5"),
capabilities=(BrowserUseCapability(),),
output_type=str,
)
async with CdpBrowserBackend.connect(cdp_url) as browser:
result = await executable.run(
"Navigate to https://example.com and describe the page.",
bindings=RunBindings.embedded(browser_backend=browser),
)
return result.output_or_raise()
The context manager creates an owned tab scope, closes its tabs on exit, and disconnects its CDP client while leaving the browser process and unrelated tabs alive. The endpoint can be an HTTP(S) CDP base URL or WS(S) debugger URL. Keep CDP private: it grants broad browser control.
For a long-lived Host, connect once with Chromium.connect(cdp_url) from a13n_harness.capabilities.browser.cdp, create independent CdpBrowserBackend(runtime) scopes, and open a tab with await scope.tabs("new"). The default tab_access="owned" exposes only that scope's tabs and popups. Use CdpBrowserBackend(runtime, tab_access="global") to list and operate all actual browser tabs, including user tabs and other scopes' tabs. Global listing and selection borrow existing pages; newly created tabs remain owned by their creator. Each binding has independent logical selection, and close() only cleans up its owned targets in either mode.
Reuse a backend across Runs, supplying fresh authorization through each Run binding. await scope.attach(target_id) validates an exact surviving page during Host-directed reattachment, claiming it in owned mode or borrowing it in global mode. Both modes share the profile's login/storage state. When another binding uses the same Page, previous element and screenshot references expire; observe again before acting.
Before human input, await scope.pause() for every scope on the controlled browser and prevent new scope admission. After revoking viewer input, call scope.resume(). Pending tools return a fresh-observation instruction without replaying their original action. scope.retire() revokes access; await scope.close() also closes owned tabs; await runtime.close() disconnects without destroying Chromium. Run completion performs none of these Host lifecycle operations.
The model receives nine tools: browser_observe, browser_read, browser_navigate, browser_act, browser_wait, browser_tabs, browser_files, browser_dialog, and browser_screenshot.
A typical task navigates, observes a focused region, acts on an eN reference or a unique semantic locator, and reads or waits to verify the outcome. browser_act takes one action at a time, including fill/type, click/hover, key chords, check, native select, and scroll. For example, its arguments can be:
{"action": {"kind": "fill", "target": {"kind": "locator", "role": "textbox", "name": "Email"}, "text": "ada@example.com"}}
Observation filters and pagination keep large pages manageable; reading text, links, tables, or forms preserves the existing refs. Both support same-process and out-of-process frames. State values distinguish disabled, readonly, checked, selected, and expanded controls; password values are redacted. Inspect dispatch separately from verification: input delivery alone does not establish that a form submitted or a purchase succeeded.
Screenshots return JPEG content plus an sN identifier and CSS dimensions. For visual-only controls, click or hover accepts normalized coordinates in the latest viewport/clip screenshot; the reference is consumed once and checked for stale page/viewport state. Prefer semantic targets for moving content. Full-page screenshots are for observation. Use browser_files for Host-path uploads and accessible tracked download status, and browser_dialog for JavaScript prompts.
Browser access is outside the Agent Environment's sandbox and cannot enforce restrictive allowed_hosts. The Host must authorize the captured Run rather than relying on its Thread's defaults. See the browser contract.
Run the opt-in native fixtures with an already installed Chromium executable:
uv run --package a13n-harness --group test pytest \
packages/a13n-harness/tests/test_browser_cdp_native.py \
packages/a13n-harness/tests/test_browser_workflows_native.py \
--browser-executable=/path/to/chromium
The fixtures use disposable profiles and a basic password store to avoid desktop keyring prompts. If the test environment requires disabling Chromium's sandbox, explicitly add --browser-no-sandbox; it is never selected automatically for root.
Model construction
Pass a native model directly through HarnessBuilder.build(model=...), or select one in AgentSpec.model. a13n_harness.infer_model() constructs a model from supported aliases and caller-owned provider factories. create_model_http_client() builds a caller-owned httpx2 client for provider requests. Configure credentials and close owned clients in your application. See Models and Model authentication.
Execution boundary and filters
Harness prepares images for the selected Model without changing saved history or original files. Configure HarnessModelCharacteristics.image_input with ImageInputPolicy, or set image_input=None to disable preparation. See Context.
Recognized provider-history repairs are on by default; configure them through SelfHealingModelCapability or disable automatic installation with HarnessBuilder(self_healing_enabled=False). For long Threads, opt into proactive history compaction. Context recovery is enabled by default and first tries normal compaction after native context-window overflow. Add other Capabilities for policy, memory, or delegation.
A completed Run returns a HarnessState with a stable thread_id. Pass it as previous_state to continue the Thread; each new Run receives a fresh run_id. The Host persists accepted state and reconstructs credentials and other current authority on resume. State and resume covers serialization and interrupted calls.
Runnable examples and guides
- Agent application: offline streaming turns, checkpointing, and restart recovery.
- Environment Providers: construction, re-entry, and lifecycle.
- Plugins and extensions: packaged middleware, Capabilities, and Environment integrations.
- MCP tools: an in-process server and an offline Model, followed by Host-owned clients and per-Run headers.
- Harness guide: the public API by task.
Versioning
Harness and a13n-stream-protocol publish together at one exact version. Harness UI releases independently. The Harness specification owns the accepted contracts.
Metadata
Release files for a13n-harness 0.30.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| a13n_harness-0.30.2.tar.gz | 1.4 MB | Without provenance | Details for a13n_harness-0.30.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| a13n_harness-0.30.2-py3-none-any.whl | Python 3 | none | any | Details for a13n_harness-0.30.2-py3-none-any.whl |
Total release size: 2.5 MB
Release files / a13n_harness-0.30.2.tar.gz
| Download URL | a13n_harness-0.30.2.tar.gz |
|---|---|
| Size | 1.4 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0c9ea5b9b63db81da92c6bc5f80fe1f25a996cd1fee70c1b95039e1f1cbfe0f0
|
|
BLAKE2b-256 checksum How to use checksums |
1e58962d207186c8d1bcd5b4a87e15bdaa4e8491014a8652ab17786ecf96600f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / a13n_harness-0.30.2-py3-none-any.whl
| Download URL | a13n_harness-0.30.2-py3-none-any.whl |
|---|---|
| Size | 1.0 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b9dfd1ba27fc53932705b87ebcf1bf924d2c012242ed61544bdf6a4d446bd86b
|
|
BLAKE2b-256 checksum How to use checksums |
37d23bdfa1cea339efc999e1d6b089e5273a56e749699d1d9fcf6f5f079278aa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for a13n-harness 0.30.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.