environment-harness 0.2.3rc1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- environment_harness-0.2.3rc1/.gitignore +17 -0
- environment_harness-0.2.3rc1/CHANGELOG.md +29 -0
- environment_harness-0.2.3rc1/CODE_OF_CONDUCT.md +7 -0
- environment_harness-0.2.3rc1/CONTRIBUTING.md +19 -0
- environment_harness-0.2.3rc1/LICENSE +21 -0
- environment_harness-0.2.3rc1/PKG-INFO +201 -0
- environment_harness-0.2.3rc1/README.md +158 -0
- environment_harness-0.2.3rc1/SECURITY.md +47 -0
- environment_harness-0.2.3rc1/SUPPORT.md +7 -0
- environment_harness-0.2.3rc1/contracts/Action.schema.json +39 -0
- environment_harness-0.2.3rc1/contracts/AgentSpec.schema.json +39 -0
- environment_harness-0.2.3rc1/contracts/Capabilities.schema.json +59 -0
- environment_harness-0.2.3rc1/contracts/EnvironmentSpec.schema.json +174 -0
- environment_harness-0.2.3rc1/contracts/ExperimentSpec.schema.json +341 -0
- environment_harness-0.2.3rc1/contracts/Finding.schema.json +110 -0
- environment_harness-0.2.3rc1/contracts/MetricDefinition.schema.json +32 -0
- environment_harness-0.2.3rc1/contracts/Principal.schema.json +61 -0
- environment_harness-0.2.3rc1/contracts/RunPolicy.schema.json +61 -0
- environment_harness-0.2.3rc1/contracts/ScoreReport.schema.json +216 -0
- environment_harness-0.2.3rc1/contracts/Transition.schema.json +121 -0
- environment_harness-0.2.3rc1/docs/ADAPTERS.md +23 -0
- environment_harness-0.2.3rc1/docs/AGENT-INTEGRATION.md +22 -0
- environment_harness-0.2.3rc1/docs/AUTHORING.md +32 -0
- environment_harness-0.2.3rc1/docs/COMPATIBILITY.md +76 -0
- environment_harness-0.2.3rc1/docs/DEPENDENCY-SECURITY.md +17 -0
- environment_harness-0.2.3rc1/docs/PROTOCOL.md +61 -0
- environment_harness-0.2.3rc1/docs/STATUS.md +20 -0
- environment_harness-0.2.3rc1/docs/assets/environment-session-viewer.png +0 -0
- environment_harness-0.2.3rc1/docs/coordinated-sessions.md +46 -0
- environment_harness-0.2.3rc1/examples/branch_comparison.py +90 -0
- environment_harness-0.2.3rc1/examples/command_agent.py +10 -0
- environment_harness-0.2.3rc1/examples/custom_agent.py +34 -0
- environment_harness-0.2.3rc1/examples/pettingzoo_rps.py +37 -0
- environment_harness-0.2.3rc1/pyproject.toml +100 -0
- environment_harness-0.2.3rc1/src/environment_harness/__init__.py +15 -0
- environment_harness-0.2.3rc1/src/environment_harness/adapters/_subprocess.py +58 -0
- environment_harness-0.2.3rc1/src/environment_harness/adapters/environments.py +205 -0
- environment_harness-0.2.3rc1/src/environment_harness/adapters/frameworks.py +60 -0
- environment_harness-0.2.3rc1/src/environment_harness/adapters/process.py +124 -0
- environment_harness-0.2.3rc1/src/environment_harness/adapters/programs.py +196 -0
- environment_harness-0.2.3rc1/src/environment_harness/agent_state.py +29 -0
- environment_harness-0.2.3rc1/src/environment_harness/backends.py +106 -0
- environment_harness-0.2.3rc1/src/environment_harness/cli.py +225 -0
- environment_harness-0.2.3rc1/src/environment_harness/client.py +99 -0
- environment_harness-0.2.3rc1/src/environment_harness/conformance.py +65 -0
- environment_harness-0.2.3rc1/src/environment_harness/contracts.py +197 -0
- environment_harness-0.2.3rc1/src/environment_harness/errors.py +22 -0
- environment_harness-0.2.3rc1/src/environment_harness/evaluation.py +168 -0
- environment_harness-0.2.3rc1/src/environment_harness/fixtures.py +73 -0
- environment_harness-0.2.3rc1/src/environment_harness/history.py +106 -0
- environment_harness-0.2.3rc1/src/environment_harness/hosted.py +136 -0
- environment_harness-0.2.3rc1/src/environment_harness/local_viewer.py +66 -0
- environment_harness-0.2.3rc1/src/environment_harness/migrations/001_durable_sessions.sql +61 -0
- environment_harness-0.2.3rc1/src/environment_harness/operations.py +211 -0
- environment_harness-0.2.3rc1/src/environment_harness/plugins.py +49 -0
- environment_harness-0.2.3rc1/src/environment_harness/presentation.py +465 -0
- environment_harness-0.2.3rc1/src/environment_harness/py.typed +1 -0
- environment_harness-0.2.3rc1/src/environment_harness/receipts.py +33 -0
- environment_harness-0.2.3rc1/src/environment_harness/runner.py +314 -0
- environment_harness-0.2.3rc1/src/environment_harness/runtime.py +980 -0
- environment_harness-0.2.3rc1/src/environment_harness/scoring.py +66 -0
- environment_harness-0.2.3rc1/src/environment_harness/server.py +270 -0
- environment_harness-0.2.3rc1/src/environment_harness/store.py +445 -0
- environment_harness-0.2.3rc1/src/environment_harness/viewer/app.js +367 -0
- environment_harness-0.2.3rc1/src/environment_harness/viewer/client.js +55 -0
- environment_harness-0.2.3rc1/src/environment_harness/viewer/index.html +115 -0
- environment_harness-0.2.3rc1/src/environment_harness/viewer/style.css +222 -0
- environment_harness-0.2.3rc1/src/environment_harness/viewer/timeline.js +245 -0
- environment_harness-0.2.3rc1/src/environment_harness/viewer/types.js +1 -0
- environment_harness-0.2.3rc1/src/environment_harness/worker.py +42 -0
- environment_harness-0.2.3rc1/uv.toml +1 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
Production PyPI publishing now uses short-lived Trusted Publishing credentials and publishes only the reviewed Python wheel and source distribution. Releases support PEP 440 alpha, beta, and release-candidate versions while mapping those versions to npm-compatible SemVer prereleases. Package metadata now includes the rendered README, classifiers, project links, and the `py.typed` marker.
|
|
6
|
+
|
|
7
|
+
## 0.2.2 - 2026-09-18
|
|
8
|
+
|
|
9
|
+
Release publishing now extracts immutable-ID artifacts directly into the verified distribution directory before checking attestations and explicitly disables dependency caching during the tag build. Routine Dependabot version updates are grouped into one monthly pull request per ecosystem, while security updates remain immediate.
|
|
10
|
+
|
|
11
|
+
## 0.2.1 - 2026-09-17
|
|
12
|
+
|
|
13
|
+
The public SDK now includes coordinated vulnerability reporting, governance and support files, dependency cooldowns, immutable workflow and container pins, credential-free security scans, cross-platform CI, positive distribution manifests, installed-wheel smoke tests, SBOM and tag-triggered artifact-attestation release automation, and protected-release setup guidance. Release maintainers create the reviewed protected tag manually; Actions stores no long-lived release credential. Python and TypeScript coverage gates require at least 90% statements/lines and 80% branches; security-critical Python modules meet those floors independently.
|
|
14
|
+
|
|
15
|
+
Session recovery now rejects stale worker completion and protects reconciled responses. Cancellation works while a writer is active, terminates managed command process groups and reports unresolved effects. The runner validates registered agent implementations, and conformance supports coordinator closure and explicit event inputs.
|
|
16
|
+
|
|
17
|
+
Comparisons keep incompatible metric definitions and units in separate groups. Legacy reports remain readable as raw values. Large inherited records use bounded chunks and can be branched repeatedly without adding encoding layers. Existing stores require no migration. See [compatibility and protocol details](docs/COMPATIBILITY.md).
|
|
18
|
+
|
|
19
|
+
The command line gains `list`, `show` and `timeline`. `timeline` groups recorded events by the state revision an action was taken from and prints one line per participant with the observation, the attempted action and the executed outcome; `--participant`, `--kind` and `--verbose` narrow or expand it. `compare` now prints a readable summary by default, and `--json` on these commands prints the underlying records, so scripts that parsed `compare` output should pass `--json`. Comparison records include `participants` and `revision`.
|
|
20
|
+
|
|
21
|
+
The browser viewer is read-only. It groups the timeline by revision, names environments by their participants and role, collapses inherited history into one line, renders scores as cards, and uses a sandstone palette that follows the system light or dark preference. Checkpoint, pause, cancel and branch controls moved out of the viewer; they remain command-line and SDK operations.
|
|
22
|
+
|
|
23
|
+
The README's local startup now uses `serve --open` to open and connect the viewer automatically. A single-use loopback connection ticket avoids copying credentials, and tab-scoped storage keeps the local viewer connected across refreshes. Supplier API authentication remains required.
|
|
24
|
+
|
|
25
|
+
## 0.1.0
|
|
26
|
+
|
|
27
|
+
EnvironmentHarness provides persistent shared environments, participant-specific observations, checkpoints, isolated branches and recorded evidence. The local viewer supports inspection, comparison and JSONL export.
|
|
28
|
+
|
|
29
|
+
The release includes Python and TypeScript clients, an authenticated HTTP service, and runnable synthetic examples. The examples require no account or model API key. Their results demonstrate the SDK workflow and do not measure model intelligence or safety.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
EnvironmentHarness follows the [Contributor Covenant, version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/).
|
|
4
|
+
|
|
5
|
+
Be respectful, constructive, and welcoming. Harassment, intimidation, discrimination, and publication of another person's private information are not acceptable in project spaces.
|
|
6
|
+
|
|
7
|
+
Report conduct concerns privately to founders@kimpton.ai. Maintainers will review reports confidentially, avoid conflicts of interest, and may remove content or participation privileges when necessary.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Use Python 3.12 or later, uv 0.12.0, Node.js 22, and npm 11.17 or later. Run `uv sync --extra server` and `npm ci --ignore-scripts --prefix packages/typescript`. Resolution observes the seven-day dependency cooldown in [docs/DEPENDENCY-SECURITY.md](docs/DEPENDENCY-SECURITY.md).
|
|
4
|
+
|
|
5
|
+
The PostgreSQL integration test uses PostgreSQL 17.6 Alpine at an immutable container digest in the weekly workflow. Update both the version and digest deliberately when testing a newer database release.
|
|
6
|
+
|
|
7
|
+
Python and TypeScript ship as one coordinated three-component SemVer release. Keep user-facing changes under `Unreleased`; do not edit package versions individually. Patch releases contain backward-compatible fixes. Minor releases contain new capabilities and, while the SDK is below 1.0, any intentionally incompatible public change with documented migration guidance. After 1.0, incompatible public API or contract changes require a major release.
|
|
8
|
+
|
|
9
|
+
To release, create a release branch after adding notes under `Unreleased`, then run `python scripts/release_version.py prepare --bump patch` (or `minor`/`major`). It moves the accumulated notes to a dated version and synchronizes `pyproject.toml`, `environment_harness.__version__`, `uv.lock`, the TypeScript package and lockfile, the root and TypeScript README examples, and the release status. Validate the proposed tag with `python scripts/release_version.py validate --release-tag vX.Y.Z`, run the release checks, and merge the release PR normally.
|
|
10
|
+
|
|
11
|
+
After the release PR merges, copy its merge commit SHA from GitHub; do not use the newest `main` commit if later changes have landed. A release maintainer fetches `main` and tags, detaches at the recorded merge commit, and runs `python scripts/release_version.py detect`. Create the reported protected tag with `git tag vX.Y.Z <release-merge-sha>` and push only `refs/tags/vX.Y.Z`. The tag dispatches the attested publisher, which waits for independent `github-release` environment approval. Release preparation and tag creation intentionally use no stored GitHub App private key or other long-lived Actions credential. Never rebuild different artifacts under an existing version.
|
|
12
|
+
|
|
13
|
+
Before submitting a change, run `make check`, `make viewer`, `npm run typecheck --prefix packages/typescript`, and `make build`. Include a small reproducible example of the behavior you changed. Schema changes must update the generated JSON and TypeScript contracts. `src/environment_harness/presentation.py` and `packages/typescript/src/timeline.ts` must keep the same turn-grouping rules and field names so the command line and the viewer describe evidence identically. Do not change protocol semantics without describing compatibility and migration.
|
|
14
|
+
|
|
15
|
+
CI requires at least 90% statement and 80% branch coverage overall and for security-critical modules. Changed executable lines require 100% diff coverage. A changed regression test must also fail when applied to `origin/main`.
|
|
16
|
+
|
|
17
|
+
Keep domain implementations, credentials and recorded private data out of this repository. Examples and test fixtures must be synthetic or explicitly redistributable. Optional integration support should state its actual checkpoint and recovery limits.
|
|
18
|
+
|
|
19
|
+
Open a GitHub issue for a bug or integration question. Include the release version, operating system, exact command and a sanitized reproduction. Never attach credentials or a private environment store. Report security concerns privately as described in [SECURITY.md](SECURITY.md).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kimpton AI, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: environment-harness
|
|
3
|
+
Version: 0.2.3rc1
|
|
4
|
+
Summary: Durable sessions and evidence for independently implemented AI environments
|
|
5
|
+
Project-URL: Homepage, https://github.com/kimpton-ai/environment-harness
|
|
6
|
+
Project-URL: Repository, https://github.com/kimpton-ai/environment-harness
|
|
7
|
+
Project-URL: Documentation, https://github.com/kimpton-ai/environment-harness#readme
|
|
8
|
+
Project-URL: Changelog, https://github.com/kimpton-ai/environment-harness/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Issues, https://github.com/kimpton-ai/environment-harness/issues
|
|
10
|
+
Project-URL: Security, https://github.com/kimpton-ai/environment-harness/security/policy
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: ai-agents,environments,evaluation,experiments
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.12
|
|
23
|
+
Requires-Dist: jsonschema<5,>=4.26
|
|
24
|
+
Requires-Dist: pydantic<3,>=2.12.5
|
|
25
|
+
Provides-Extra: mcp
|
|
26
|
+
Requires-Dist: mcp<2,>=1.30.0; extra == 'mcp'
|
|
27
|
+
Provides-Extra: modal
|
|
28
|
+
Requires-Dist: modal<2,>=1.5.4; extra == 'modal'
|
|
29
|
+
Provides-Extra: pettingzoo
|
|
30
|
+
Requires-Dist: pettingzoo<2,>=1.25; extra == 'pettingzoo'
|
|
31
|
+
Requires-Dist: pygame<3,>=2.6.1; extra == 'pettingzoo'
|
|
32
|
+
Provides-Extra: postgres
|
|
33
|
+
Requires-Dist: psycopg[binary]<4,>=3.3.3; extra == 'postgres'
|
|
34
|
+
Provides-Extra: server
|
|
35
|
+
Requires-Dist: fastapi<1,>=0.135.1; extra == 'server'
|
|
36
|
+
Requires-Dist: uvicorn<1,>=0.41; extra == 'server'
|
|
37
|
+
Provides-Extra: signatures
|
|
38
|
+
Requires-Dist: cryptography<51,>=50.0.1; extra == 'signatures'
|
|
39
|
+
Provides-Extra: verifiers
|
|
40
|
+
Requires-Dist: datasets<6,>=5.0.1; extra == 'verifiers'
|
|
41
|
+
Requires-Dist: verifiers<0.4,>=0.3.1; extra == 'verifiers'
|
|
42
|
+
Description-Content-Type: text/markdown
|
|
43
|
+
|
|
44
|
+
# EnvironmentHarness
|
|
45
|
+
|
|
46
|
+
[](https://github.com/kimpton-ai/environment-harness/actions/workflows/ci.yml)
|
|
47
|
+
[](https://app.codecov.io/gh/kimpton-ai/environment-harness)
|
|
48
|
+
[](https://www.python.org/downloads/)
|
|
49
|
+
[](https://github.com/kimpton-ai/environment-harness/blob/main/LICENSE)
|
|
50
|
+
|
|
51
|
+
Run agents in persistent shared environments, then inspect exactly what they observed, attempted, and changed.
|
|
52
|
+
|
|
53
|
+
EnvironmentHarness is an MIT-licensed SDK for evaluations that unfold over time. It records participant-specific observations, actions, outcomes, checkpoints, score reports, and branch lineage as durable evidence.
|
|
54
|
+
|
|
55
|
+
[Install](#install) · [Try it locally](#try-it-locally) · [Connect an agent](https://github.com/kimpton-ai/environment-harness/blob/main/docs/AGENT-INTEGRATION.md) · [Implement an environment](https://github.com/kimpton-ai/environment-harness/blob/main/docs/AUTHORING.md) · [Protocol](https://github.com/kimpton-ai/environment-harness/blob/main/docs/PROTOCOL.md) · [Release scope](https://github.com/kimpton-ai/environment-harness/blob/main/docs/STATUS.md)
|
|
56
|
+
|
|
57
|
+
## What you can do
|
|
58
|
+
|
|
59
|
+
- Run one or more agents against stateful environment rules.
|
|
60
|
+
- Give each participant a different private observation of the same shared state.
|
|
61
|
+
- Record observations, attempted actions, executed outcomes, scores, costs, and artifacts.
|
|
62
|
+
- Checkpoint an environment session, branch it with a declared intervention, and continue both sessions.
|
|
63
|
+
- Inspect a timeline, compare related environment sessions, or export the evidence as JSONL.
|
|
64
|
+
|
|
65
|
+
You provide the environment rules, agent programs, and grading method. EnvironmentHarness coordinates the environment session and preserves the evidence.
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
Your environment + agents + scorer
|
|
69
|
+
│
|
|
70
|
+
▼
|
|
71
|
+
EnvironmentSession
|
|
72
|
+
records every state revision
|
|
73
|
+
│
|
|
74
|
+
▼
|
|
75
|
+
Python / CLI / local viewer
|
|
76
|
+
/ JSONL
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Install
|
|
80
|
+
|
|
81
|
+
Install the stable Python SDK from PyPI:
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
python -m pip install environment-harness
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Add the local HTTP service and viewer when you need them:
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
python -m pip install "environment-harness[server]"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Release candidates use PEP 440 versions such as `0.2.3rc1`. Pip excludes prereleases from ordinary installs; test one by requesting its exact version or by opting in:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
python -m pip install "environment-harness==0.2.3rc1"
|
|
97
|
+
python -m pip install --pre --upgrade environment-harness
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Try it locally
|
|
101
|
+
|
|
102
|
+
You need macOS or Linux, Python 3.12 or later, and [uv 0.12.0 or later](https://docs.astral.sh/uv/getting-started/installation/). The demo uses synthetic agents, so it needs no account, model API key, or paid service.
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
git clone --branch v0.2.3rc1 --depth 1 https://github.com/kimpton-ai/environment-harness.git
|
|
106
|
+
cd environment-harness
|
|
107
|
+
uv sync --extra server
|
|
108
|
+
uv run python examples/branch_comparison.py --store .local/branch-demo
|
|
109
|
+
uv run environment-harness --store .local/branch-demo serve --open
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The last command serves something, but only on your computer:
|
|
113
|
+
|
|
114
|
+
- a local authenticated API at `http://127.0.0.1:8765`
|
|
115
|
+
- a read-only browser viewer for the evidence in `.local/branch-demo`
|
|
116
|
+
|
|
117
|
+
It does not deploy or publish the environment session. `--open` creates a short-lived local login link and opens the viewer. Press `Ctrl+C` in the terminal to stop the service.
|
|
118
|
+
|
|
119
|
+
### What the demo means
|
|
120
|
+
|
|
121
|
+
The example creates one original environment session with a shared counter. Alice and Bob each add `1` per turn:
|
|
122
|
+
|
|
123
|
+
1. After three turns, the original session's shared total is `6`.
|
|
124
|
+
2. The example saves a checkpoint and creates a separate branched session from it.
|
|
125
|
+
3. A declared intervention changes only the branched session's starting total from `6` to `20`.
|
|
126
|
+
4. Both sessions run for two more turns. The original finishes at `10`; the branch finishes at `24`.
|
|
127
|
+
|
|
128
|
+
The totals are values in the synthetic environment's shared state. They are not the number of agents, scores of agent quality, or independent statistical results. The example exists to demonstrate state, lineage, intervention, and recorded evidence.
|
|
129
|
+
|
|
130
|
+
### What the viewer shows
|
|
131
|
+
|
|
132
|
+
The viewer is an evidence inspector, not a control panel:
|
|
133
|
+
|
|
134
|
+

|
|
135
|
+
|
|
136
|
+
1. The **Environment sessions** list lets you open the original or branched session. Check two boxes to compare them.
|
|
137
|
+
2. **Timeline** groups evidence by state revision. Each participant row shows the observation delivered to that participant, the action it attempted, and the outcome the environment executed.
|
|
138
|
+
3. **Scores and findings** shows reports submitted by your scorer. In this demo, `synthetic total` is just the final counter value.
|
|
139
|
+
4. **Environment comparison** shows what the sessions share, the intervention applied to the branch, and their recorded results.
|
|
140
|
+
|
|
141
|
+
The viewer never changes an environment session. Use the Python SDK or CLI for checkpoint, branch, resume, cancel, and execution operations.
|
|
142
|
+
|
|
143
|
+
## Use your own agent
|
|
144
|
+
|
|
145
|
+
Run the included external JSON program through the command-agent boundary:
|
|
146
|
+
|
|
147
|
+
```sh
|
|
148
|
+
uv run python examples/custom_agent.py --store .local/custom-agent
|
|
149
|
+
uv run environment-harness --store .local/custom-agent serve --open
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
A Python agent implements `act(observation) -> dict`. An external program can instead read one JSON observation from stdin and write one JSON action to stdout. Your integration keeps ownership of prompts, model providers, tools, credentials, and spending limits.
|
|
153
|
+
|
|
154
|
+
See [Connect an agent](https://github.com/kimpton-ai/environment-harness/blob/main/docs/AGENT-INTEGRATION.md) for the complete contract and [custom_agent.py](https://github.com/kimpton-ai/environment-harness/blob/main/examples/custom_agent.py) for a working example.
|
|
155
|
+
|
|
156
|
+
## Use the Python API
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
from environment_harness import AgentSpec, EnvironmentSession, EvidenceStore, ExperimentSpec, Principal
|
|
160
|
+
from environment_harness.fixtures import SyntheticAgent, SyntheticEnvironment
|
|
161
|
+
from environment_harness.runner import run
|
|
162
|
+
|
|
163
|
+
environment = SyntheticEnvironment()
|
|
164
|
+
session = EnvironmentSession(EvidenceStore(".local/experiment"), environment)
|
|
165
|
+
researcher = Principal(tenant="local", subject="researcher", role="researcher")
|
|
166
|
+
experiment = ExperimentSpec(
|
|
167
|
+
environment=environment.spec,
|
|
168
|
+
participants=(
|
|
169
|
+
AgentSpec(id="alice", implementation="synthetic-agent@1", policy_version="1"),
|
|
170
|
+
),
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
environment_session = session.create(experiment, researcher)
|
|
174
|
+
run(
|
|
175
|
+
session,
|
|
176
|
+
environment_session["id"],
|
|
177
|
+
researcher,
|
|
178
|
+
{"alice": SyntheticAgent()},
|
|
179
|
+
turns=5,
|
|
180
|
+
)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The local Python API is a trusted embedding interface. A local command subprocess is also not an operating-system security sandbox. Run hostile programs in an isolated backend with explicitly scoped network access.
|
|
184
|
+
|
|
185
|
+
## Find the right guide
|
|
186
|
+
|
|
187
|
+
| Goal | Guide |
|
|
188
|
+
| --- | --- |
|
|
189
|
+
| Connect a Python agent, model integration, or JSON program | [Agent integration](https://github.com/kimpton-ai/environment-harness/blob/main/docs/AGENT-INTEGRATION.md) |
|
|
190
|
+
| Implement and package environment rules | [Environment authoring](https://github.com/kimpton-ai/environment-harness/blob/main/docs/AUTHORING.md) |
|
|
191
|
+
| Understand checkpoints, branches, and coordinated sessions | [Coordinated sessions](https://github.com/kimpton-ai/environment-harness/blob/main/docs/coordinated-sessions.md) |
|
|
192
|
+
| Use the authenticated HTTP API | [Protocol](https://github.com/kimpton-ai/environment-harness/blob/main/docs/PROTOCOL.md) |
|
|
193
|
+
| Use the TypeScript client | [TypeScript package](https://github.com/kimpton-ai/environment-harness/blob/main/packages/typescript/README.md) |
|
|
194
|
+
| Check adapter and isolation boundaries | [Adapters](https://github.com/kimpton-ai/environment-harness/blob/main/docs/ADAPTERS.md) |
|
|
195
|
+
| Check compatibility and release limits | [Compatibility](https://github.com/kimpton-ai/environment-harness/blob/main/docs/COMPATIBILITY.md) · [Release scope](https://github.com/kimpton-ai/environment-harness/blob/main/docs/STATUS.md) |
|
|
196
|
+
|
|
197
|
+
## Project
|
|
198
|
+
|
|
199
|
+
[Contributing](https://github.com/kimpton-ai/environment-harness/blob/main/CONTRIBUTING.md) · [Support](https://github.com/kimpton-ai/environment-harness/blob/main/SUPPORT.md) · [Security](https://github.com/kimpton-ai/environment-harness/blob/main/SECURITY.md) · [Changelog](https://github.com/kimpton-ai/environment-harness/blob/main/CHANGELOG.md) · [MIT license](https://github.com/kimpton-ai/environment-harness/blob/main/LICENSE)
|
|
200
|
+
|
|
201
|
+
Report vulnerabilities privately through [SECURITY.md](https://github.com/kimpton-ai/environment-harness/blob/main/SECURITY.md). Do not put credentials or private environment sessions in a public issue.
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# EnvironmentHarness
|
|
2
|
+
|
|
3
|
+
[](https://github.com/kimpton-ai/environment-harness/actions/workflows/ci.yml)
|
|
4
|
+
[](https://app.codecov.io/gh/kimpton-ai/environment-harness)
|
|
5
|
+
[](https://www.python.org/downloads/)
|
|
6
|
+
[](https://github.com/kimpton-ai/environment-harness/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+
Run agents in persistent shared environments, then inspect exactly what they observed, attempted, and changed.
|
|
9
|
+
|
|
10
|
+
EnvironmentHarness is an MIT-licensed SDK for evaluations that unfold over time. It records participant-specific observations, actions, outcomes, checkpoints, score reports, and branch lineage as durable evidence.
|
|
11
|
+
|
|
12
|
+
[Install](#install) · [Try it locally](#try-it-locally) · [Connect an agent](https://github.com/kimpton-ai/environment-harness/blob/main/docs/AGENT-INTEGRATION.md) · [Implement an environment](https://github.com/kimpton-ai/environment-harness/blob/main/docs/AUTHORING.md) · [Protocol](https://github.com/kimpton-ai/environment-harness/blob/main/docs/PROTOCOL.md) · [Release scope](https://github.com/kimpton-ai/environment-harness/blob/main/docs/STATUS.md)
|
|
13
|
+
|
|
14
|
+
## What you can do
|
|
15
|
+
|
|
16
|
+
- Run one or more agents against stateful environment rules.
|
|
17
|
+
- Give each participant a different private observation of the same shared state.
|
|
18
|
+
- Record observations, attempted actions, executed outcomes, scores, costs, and artifacts.
|
|
19
|
+
- Checkpoint an environment session, branch it with a declared intervention, and continue both sessions.
|
|
20
|
+
- Inspect a timeline, compare related environment sessions, or export the evidence as JSONL.
|
|
21
|
+
|
|
22
|
+
You provide the environment rules, agent programs, and grading method. EnvironmentHarness coordinates the environment session and preserves the evidence.
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
Your environment + agents + scorer
|
|
26
|
+
│
|
|
27
|
+
▼
|
|
28
|
+
EnvironmentSession
|
|
29
|
+
records every state revision
|
|
30
|
+
│
|
|
31
|
+
▼
|
|
32
|
+
Python / CLI / local viewer
|
|
33
|
+
/ JSONL
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Install
|
|
37
|
+
|
|
38
|
+
Install the stable Python SDK from PyPI:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
python -m pip install environment-harness
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Add the local HTTP service and viewer when you need them:
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
python -m pip install "environment-harness[server]"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Release candidates use PEP 440 versions such as `0.2.3rc1`. Pip excludes prereleases from ordinary installs; test one by requesting its exact version or by opting in:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
python -m pip install "environment-harness==0.2.3rc1"
|
|
54
|
+
python -m pip install --pre --upgrade environment-harness
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Try it locally
|
|
58
|
+
|
|
59
|
+
You need macOS or Linux, Python 3.12 or later, and [uv 0.12.0 or later](https://docs.astral.sh/uv/getting-started/installation/). The demo uses synthetic agents, so it needs no account, model API key, or paid service.
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
git clone --branch v0.2.3rc1 --depth 1 https://github.com/kimpton-ai/environment-harness.git
|
|
63
|
+
cd environment-harness
|
|
64
|
+
uv sync --extra server
|
|
65
|
+
uv run python examples/branch_comparison.py --store .local/branch-demo
|
|
66
|
+
uv run environment-harness --store .local/branch-demo serve --open
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The last command serves something, but only on your computer:
|
|
70
|
+
|
|
71
|
+
- a local authenticated API at `http://127.0.0.1:8765`
|
|
72
|
+
- a read-only browser viewer for the evidence in `.local/branch-demo`
|
|
73
|
+
|
|
74
|
+
It does not deploy or publish the environment session. `--open` creates a short-lived local login link and opens the viewer. Press `Ctrl+C` in the terminal to stop the service.
|
|
75
|
+
|
|
76
|
+
### What the demo means
|
|
77
|
+
|
|
78
|
+
The example creates one original environment session with a shared counter. Alice and Bob each add `1` per turn:
|
|
79
|
+
|
|
80
|
+
1. After three turns, the original session's shared total is `6`.
|
|
81
|
+
2. The example saves a checkpoint and creates a separate branched session from it.
|
|
82
|
+
3. A declared intervention changes only the branched session's starting total from `6` to `20`.
|
|
83
|
+
4. Both sessions run for two more turns. The original finishes at `10`; the branch finishes at `24`.
|
|
84
|
+
|
|
85
|
+
The totals are values in the synthetic environment's shared state. They are not the number of agents, scores of agent quality, or independent statistical results. The example exists to demonstrate state, lineage, intervention, and recorded evidence.
|
|
86
|
+
|
|
87
|
+
### What the viewer shows
|
|
88
|
+
|
|
89
|
+
The viewer is an evidence inspector, not a control panel:
|
|
90
|
+
|
|
91
|
+

|
|
92
|
+
|
|
93
|
+
1. The **Environment sessions** list lets you open the original or branched session. Check two boxes to compare them.
|
|
94
|
+
2. **Timeline** groups evidence by state revision. Each participant row shows the observation delivered to that participant, the action it attempted, and the outcome the environment executed.
|
|
95
|
+
3. **Scores and findings** shows reports submitted by your scorer. In this demo, `synthetic total` is just the final counter value.
|
|
96
|
+
4. **Environment comparison** shows what the sessions share, the intervention applied to the branch, and their recorded results.
|
|
97
|
+
|
|
98
|
+
The viewer never changes an environment session. Use the Python SDK or CLI for checkpoint, branch, resume, cancel, and execution operations.
|
|
99
|
+
|
|
100
|
+
## Use your own agent
|
|
101
|
+
|
|
102
|
+
Run the included external JSON program through the command-agent boundary:
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
uv run python examples/custom_agent.py --store .local/custom-agent
|
|
106
|
+
uv run environment-harness --store .local/custom-agent serve --open
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
A Python agent implements `act(observation) -> dict`. An external program can instead read one JSON observation from stdin and write one JSON action to stdout. Your integration keeps ownership of prompts, model providers, tools, credentials, and spending limits.
|
|
110
|
+
|
|
111
|
+
See [Connect an agent](https://github.com/kimpton-ai/environment-harness/blob/main/docs/AGENT-INTEGRATION.md) for the complete contract and [custom_agent.py](https://github.com/kimpton-ai/environment-harness/blob/main/examples/custom_agent.py) for a working example.
|
|
112
|
+
|
|
113
|
+
## Use the Python API
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
from environment_harness import AgentSpec, EnvironmentSession, EvidenceStore, ExperimentSpec, Principal
|
|
117
|
+
from environment_harness.fixtures import SyntheticAgent, SyntheticEnvironment
|
|
118
|
+
from environment_harness.runner import run
|
|
119
|
+
|
|
120
|
+
environment = SyntheticEnvironment()
|
|
121
|
+
session = EnvironmentSession(EvidenceStore(".local/experiment"), environment)
|
|
122
|
+
researcher = Principal(tenant="local", subject="researcher", role="researcher")
|
|
123
|
+
experiment = ExperimentSpec(
|
|
124
|
+
environment=environment.spec,
|
|
125
|
+
participants=(
|
|
126
|
+
AgentSpec(id="alice", implementation="synthetic-agent@1", policy_version="1"),
|
|
127
|
+
),
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
environment_session = session.create(experiment, researcher)
|
|
131
|
+
run(
|
|
132
|
+
session,
|
|
133
|
+
environment_session["id"],
|
|
134
|
+
researcher,
|
|
135
|
+
{"alice": SyntheticAgent()},
|
|
136
|
+
turns=5,
|
|
137
|
+
)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
The local Python API is a trusted embedding interface. A local command subprocess is also not an operating-system security sandbox. Run hostile programs in an isolated backend with explicitly scoped network access.
|
|
141
|
+
|
|
142
|
+
## Find the right guide
|
|
143
|
+
|
|
144
|
+
| Goal | Guide |
|
|
145
|
+
| --- | --- |
|
|
146
|
+
| Connect a Python agent, model integration, or JSON program | [Agent integration](https://github.com/kimpton-ai/environment-harness/blob/main/docs/AGENT-INTEGRATION.md) |
|
|
147
|
+
| Implement and package environment rules | [Environment authoring](https://github.com/kimpton-ai/environment-harness/blob/main/docs/AUTHORING.md) |
|
|
148
|
+
| Understand checkpoints, branches, and coordinated sessions | [Coordinated sessions](https://github.com/kimpton-ai/environment-harness/blob/main/docs/coordinated-sessions.md) |
|
|
149
|
+
| Use the authenticated HTTP API | [Protocol](https://github.com/kimpton-ai/environment-harness/blob/main/docs/PROTOCOL.md) |
|
|
150
|
+
| Use the TypeScript client | [TypeScript package](https://github.com/kimpton-ai/environment-harness/blob/main/packages/typescript/README.md) |
|
|
151
|
+
| Check adapter and isolation boundaries | [Adapters](https://github.com/kimpton-ai/environment-harness/blob/main/docs/ADAPTERS.md) |
|
|
152
|
+
| Check compatibility and release limits | [Compatibility](https://github.com/kimpton-ai/environment-harness/blob/main/docs/COMPATIBILITY.md) · [Release scope](https://github.com/kimpton-ai/environment-harness/blob/main/docs/STATUS.md) |
|
|
153
|
+
|
|
154
|
+
## Project
|
|
155
|
+
|
|
156
|
+
[Contributing](https://github.com/kimpton-ai/environment-harness/blob/main/CONTRIBUTING.md) · [Support](https://github.com/kimpton-ai/environment-harness/blob/main/SUPPORT.md) · [Security](https://github.com/kimpton-ai/environment-harness/blob/main/SECURITY.md) · [Changelog](https://github.com/kimpton-ai/environment-harness/blob/main/CHANGELOG.md) · [MIT license](https://github.com/kimpton-ai/environment-harness/blob/main/LICENSE)
|
|
157
|
+
|
|
158
|
+
Report vulnerabilities privately through [SECURITY.md](https://github.com/kimpton-ai/environment-harness/blob/main/SECURITY.md). Do not put credentials or private environment sessions in a public issue.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Security policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
Only the latest immutable GitHub release is supported. The `main` branch is unreleased development. Older releases require upgrading unless a maintainer explicitly announces extended support.
|
|
6
|
+
|
|
7
|
+
## Report a vulnerability privately
|
|
8
|
+
|
|
9
|
+
Use [GitHub Private Vulnerability Reporting](https://github.com/kimpton-ai/environment-harness/security/advisories/new) as the primary reporting path. If that is unavailable, email support@kimpton.ai with the subject `EnvironmentHarness security`.
|
|
10
|
+
|
|
11
|
+
Include:
|
|
12
|
+
|
|
13
|
+
- the affected release or commit and the expected impact;
|
|
14
|
+
- a minimal synthetic reproduction and relevant sanitized configuration;
|
|
15
|
+
- the suspected attack path and affected security boundary; and
|
|
16
|
+
- whether the issue or exploit has been disclosed elsewhere.
|
|
17
|
+
|
|
18
|
+
Do not send live credentials, private trajectories, production environment stores, supplier code, deployment state, or an unnecessary working exploit.
|
|
19
|
+
|
|
20
|
+
Maintainers aim to acknowledge a report within five business days. This is a target, not a contractual SLA or bug bounty. The security team will validate scope, identify affected versions, assign a primary owner, coordinate remediation and disclosure, publish an advisory, and credit the reporter if desired.
|
|
21
|
+
|
|
22
|
+
Please wait for an agreed disclosure date. Fixes and exploit details remain private until patched artifacts and the advisory are ready. The advisory will identify affected and fixed versions, mitigations, CVE/GHSA identifiers when applicable, and any required credential rotation.
|
|
23
|
+
|
|
24
|
+
## Security boundaries
|
|
25
|
+
|
|
26
|
+
EnvironmentHarness enforces authenticated HTTP principals, tenant/environment/participant scope, generation checks, and evidence filtering. The researcher viewer is not an authorization boundary.
|
|
27
|
+
|
|
28
|
+
The following remain trusted:
|
|
29
|
+
|
|
30
|
+
- Python callers with local access to an `EnvironmentSession` or its store;
|
|
31
|
+
- installed plugins and database owners; and
|
|
32
|
+
- command subprocesses launched without a separate operating-system isolation boundary.
|
|
33
|
+
|
|
34
|
+
Use an isolated backend for hostile programs. The deployer or private deployment repository owns production TLS, reverse proxies, cloud IAM, secrets, backups, logging, network policy, and request-rate controls. Keep private suppliers, marketplace logic, credentials, deployment state, production environment sessions, and recorded launches outside this public SDK.
|
|
35
|
+
|
|
36
|
+
## Dependency and CI incidents
|
|
37
|
+
|
|
38
|
+
Dependency releases are held for 168 hours before adoption, including security updates, unless an exact tracked exception is approved by a security CODEOWNER. Vulnerability and malware scanning and routine dependency alerts are immediate; they are distinct from private vulnerability reports. See [the dependency and supply-chain policy](docs/DEPENDENCY-SECURITY.md).
|
|
39
|
+
|
|
40
|
+
If untrusted workflow code could access a credential or writable identity:
|
|
41
|
+
|
|
42
|
+
1. Revoke the affected credentials first.
|
|
43
|
+
2. Inspect at least 30 days of workflow runs and the complete commit ranges.
|
|
44
|
+
3. Delete potentially poisoned caches and artifacts.
|
|
45
|
+
4. Rotate every credential reachable by those jobs.
|
|
46
|
+
|
|
47
|
+
Prefer job-scoped OIDC credentials lasting minutes. Exceptional static release credentials must expire within 24 hours.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Support
|
|
2
|
+
|
|
3
|
+
Use [GitHub Discussions](https://github.com/kimpton-ai/environment-harness/discussions) for usage questions and [GitHub Issues](https://github.com/kimpton-ai/environment-harness/issues) for reproducible defects.
|
|
4
|
+
|
|
5
|
+
Include the EnvironmentHarness version, operating system, Python/Node version, exact command, and a minimal synthetic reproduction. Do not attach credentials, private environment sessions, supplier code, deployment state, or recorded launches.
|
|
6
|
+
|
|
7
|
+
Report vulnerabilities privately as described in [SECURITY.md](SECURITY.md).
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$id": "urn:environment-harness:v1:Action",
|
|
3
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
|
+
"additionalProperties": false,
|
|
5
|
+
"properties": {
|
|
6
|
+
"observation_id": {
|
|
7
|
+
"title": "Observation Id",
|
|
8
|
+
"type": "string"
|
|
9
|
+
},
|
|
10
|
+
"operation_id": {
|
|
11
|
+
"pattern": "^[a-zA-Z0-9_-]{1,128}$",
|
|
12
|
+
"title": "Operation Id",
|
|
13
|
+
"type": "string"
|
|
14
|
+
},
|
|
15
|
+
"participant": {
|
|
16
|
+
"title": "Participant",
|
|
17
|
+
"type": "string"
|
|
18
|
+
},
|
|
19
|
+
"payload": {
|
|
20
|
+
"additionalProperties": true,
|
|
21
|
+
"title": "Payload",
|
|
22
|
+
"type": "object"
|
|
23
|
+
},
|
|
24
|
+
"revision": {
|
|
25
|
+
"minimum": 0,
|
|
26
|
+
"title": "Revision",
|
|
27
|
+
"type": "integer"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"required": [
|
|
31
|
+
"operation_id",
|
|
32
|
+
"participant",
|
|
33
|
+
"observation_id",
|
|
34
|
+
"revision",
|
|
35
|
+
"payload"
|
|
36
|
+
],
|
|
37
|
+
"title": "Action",
|
|
38
|
+
"type": "object"
|
|
39
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$id": "urn:environment-harness:v1:AgentSpec",
|
|
3
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
|
+
"additionalProperties": false,
|
|
5
|
+
"properties": {
|
|
6
|
+
"checkpoint": {
|
|
7
|
+
"default": false,
|
|
8
|
+
"title": "Checkpoint",
|
|
9
|
+
"type": "boolean"
|
|
10
|
+
},
|
|
11
|
+
"config": {
|
|
12
|
+
"additionalProperties": true,
|
|
13
|
+
"title": "Config",
|
|
14
|
+
"type": "object"
|
|
15
|
+
},
|
|
16
|
+
"id": {
|
|
17
|
+
"pattern": "^[a-zA-Z0-9_-]{1,80}$",
|
|
18
|
+
"title": "Id",
|
|
19
|
+
"type": "string"
|
|
20
|
+
},
|
|
21
|
+
"implementation": {
|
|
22
|
+
"minLength": 1,
|
|
23
|
+
"title": "Implementation",
|
|
24
|
+
"type": "string"
|
|
25
|
+
},
|
|
26
|
+
"policy_version": {
|
|
27
|
+
"minLength": 1,
|
|
28
|
+
"title": "Policy Version",
|
|
29
|
+
"type": "string"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"required": [
|
|
33
|
+
"id",
|
|
34
|
+
"implementation",
|
|
35
|
+
"policy_version"
|
|
36
|
+
],
|
|
37
|
+
"title": "AgentSpec",
|
|
38
|
+
"type": "object"
|
|
39
|
+
}
|