From 2324db4c99f91f08de8d88eb69e335023b526493 Mon Sep 17 00:00:00 2001 From: Abir Abbas Date: Fri, 14 Aug 2026 23:38:38 -0400 Subject: [PATCH 1/8] feat: make aforge exec the default harness --- .env.example | 6 ++++-- Dockerfile | 10 ++++++++-- README.md | 4 ++++ docker-compose.yml | 3 ++- pyproject.toml | 2 +- src/contract_af/app.py | 1 + src/contract_af/config.py | 10 +++++++++- tests/test_config.py | 28 ++++++++++++++++++++++++++++ 8 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 tests/test_config.py diff --git a/.env.example b/.env.example index 283ccc6..f7298e9 100644 --- a/.env.example +++ b/.env.example @@ -4,7 +4,9 @@ OPENROUTER_API_KEY= # Optional: API key required when the control plane enforces auth AGENTFIELD_API_KEY= -# Optional model/provider overrides -HARNESS_PROVIDER=opencode +# AForge exec is the default. Set HARNESS_PROVIDER=opencode to roll back. +HARNESS_PROVIDER=aforge +AGENTFIELD_AFORGE_COMMAND=exec +# CONTRACT_AF_AFORGE_BIN=/absolute/path/to/aforge HARNESS_MODEL=openrouter/moonshotai/kimi-k2.5 AI_MODEL=openrouter/moonshotai/kimi-k2.5 diff --git a/Dockerfile b/Dockerfile index 17b87d6..331d445 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,7 @@ +ARG AFORGE_IMAGE=ghcr.io/agent-field/aforge-v2:chat-v2-exec +FROM ${AFORGE_IMAGE} AS aforge + + FROM python:3.11-slim AS builder ENV PYTHONDONTWRITEBYTECODE=1 \ @@ -14,7 +18,7 @@ COPY pyproject.toml README.md ./ COPY src/ src/ RUN pip install --no-cache-dir --prefix=/install \ - "agentfield>=0.1.47" \ + "agentfield @ git+https://github.com/Agent-Field/agentfield.git@bfd34426d1bdec3cbbfa946682a22ef0a1b91503#subdirectory=sdk/python" \ "pydantic>=2.0" \ "httpx>=0.27" \ "python-dotenv>=1.0" \ @@ -28,7 +32,8 @@ FROM python:3.11-slim AS runtime ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ AGENTFIELD_SERVER=http://agentfield:8080 \ - HARNESS_PROVIDER=opencode \ + HARNESS_PROVIDER=aforge \ + AGENTFIELD_AFORGE_COMMAND=exec \ HARNESS_MODEL=openrouter/moonshotai/kimi-k2.5 \ AI_MODEL=openrouter/moonshotai/kimi-k2.5 \ PORT=8004 \ @@ -54,6 +59,7 @@ RUN mkdir -p /home/contractaf/.config/opencode && \ chown -R contractaf:contractaf /home/contractaf/.config COPY --from=builder /install /usr/local +COPY --from=aforge /aforge /usr/local/bin/aforge COPY src/ /app/src/ USER contractaf diff --git a/README.md b/README.md index 16e0462..2b5c386 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,10 @@ docker compose up --build Starts AgentField control plane (`http://localhost:8080`) + Contract-AF agent. +AForge `exec` is the default coding harness and is included in the container. +Set `HARNESS_PROVIDER=opencode` to roll back, or set +`AGENTFIELD_AFORGE_COMMAND=do` to explicitly use AForge orchestration. + ```bash curl -X POST http://localhost:8080/api/v1/execute/async/contract-af.analyze \ -H "Content-Type: application/json" \ diff --git a/docker-compose.yml b/docker-compose.yml index 0061a07..fb930d5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,7 +22,8 @@ services: - AGENTFIELD_SERVER=http://agentfield:8080 - AGENTFIELD_API_KEY=${AGENTFIELD_API_KEY:-} - AGENT_CALLBACK_URL=http://contract-af:8004 - - HARNESS_PROVIDER=opencode + - HARNESS_PROVIDER=${HARNESS_PROVIDER:-aforge} + - AGENTFIELD_AFORGE_COMMAND=${AGENTFIELD_AFORGE_COMMAND:-exec} - HARNESS_MODEL=${HARNESS_MODEL:-openrouter/moonshotai/kimi-k2.5} - AI_MODEL=${AI_MODEL:-openrouter/moonshotai/kimi-k2.5} - OPENROUTER_API_KEY=${OPENROUTER_API_KEY} diff --git a/pyproject.toml b/pyproject.toml index a8415cc..0439600 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ version = "0.1.0" description = "Legal contract risk analyzer — finds dangerous clauses, proves exploitability" requires-python = ">=3.10" dependencies = [ - "agentfield", + "agentfield @ git+https://github.com/Agent-Field/agentfield.git@bfd34426d1bdec3cbbfa946682a22ef0a1b91503#subdirectory=sdk/python", "pydantic>=2.0", "fastapi>=0.100", "uvicorn>=0.20", diff --git a/src/contract_af/app.py b/src/contract_af/app.py index b6b1626..acbf007 100644 --- a/src/contract_af/app.py +++ b/src/contract_af/app.py @@ -44,6 +44,7 @@ max_turns=_ai_config.max_turns, env=_ai_config.provider_env(), opencode_bin=_ai_config.opencode_bin, + aforge_bin=_ai_config.aforge_bin, permission_mode="auto", ), ai_config=AIConfig( diff --git a/src/contract_af/config.py b/src/contract_af/config.py index 7a719e4..65a0dbc 100644 --- a/src/contract_af/config.py +++ b/src/contract_af/config.py @@ -9,7 +9,7 @@ class AIIntegrationConfig(BaseModel): provider: str = Field( default_factory=lambda: os.getenv( - "CONTRACT_AF_PROVIDER", os.getenv("HARNESS_PROVIDER", "opencode") + "CONTRACT_AF_PROVIDER", os.getenv("HARNESS_PROVIDER", "aforge") ) ) harness_model: str = Field( @@ -33,6 +33,11 @@ class AIIntegrationConfig(BaseModel): opencode_bin: str = Field( default_factory=lambda: os.getenv("CONTRACT_AF_OPENCODE_BIN", "opencode") ) + aforge_bin: str = Field( + default_factory=lambda: os.getenv( + "CONTRACT_AF_AFORGE_BIN", os.getenv("AFORGE_BIN", "aforge") + ) + ) opencode_server: str | None = Field( default_factory=lambda: os.getenv( "CONTRACT_AF_OPENCODE_SERVER", os.getenv("OPENCODE_SERVER") @@ -53,6 +58,9 @@ def provider_env(self) -> dict[str, str]: env: dict[str, str] = { key: value for key in env_keys if (value := os.getenv(key)) } + env["AGENTFIELD_AFORGE_COMMAND"] = os.getenv( + "AGENTFIELD_AFORGE_COMMAND", "exec" + ) xdg = os.getenv("XDG_DATA_HOME") or os.path.join( tempfile.gettempdir(), "opencode-shared-data" ) diff --git a/tests/test_config.py b/tests/test_config.py new file mode 100644 index 0000000..c8d3c3c --- /dev/null +++ b/tests/test_config.py @@ -0,0 +1,28 @@ +from __future__ import annotations + +import pytest + +from contract_af.config import AIIntegrationConfig + + +def test_aforge_exec_is_the_default_harness(monkeypatch: pytest.MonkeyPatch) -> None: + for key in ( + "CONTRACT_AF_PROVIDER", + "HARNESS_PROVIDER", + "CONTRACT_AF_AFORGE_BIN", + "AFORGE_BIN", + "AGENTFIELD_AFORGE_COMMAND", + ): + monkeypatch.delenv(key, raising=False) + + config = AIIntegrationConfig.from_env() + + assert config.provider == "aforge" + assert config.aforge_bin == "aforge" + assert config.provider_env()["AGENTFIELD_AFORGE_COMMAND"] == "exec" + + +def test_opencode_remains_an_explicit_rollback(monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setenv("HARNESS_PROVIDER", "opencode") + + assert AIIntegrationConfig.from_env().provider == "opencode" From c63c3a93192a453832347fec3dbe43d9ac8ab277 Mon Sep 17 00:00:00 2001 From: Abir Abbas Date: Mon, 17 Aug 2026 11:22:02 -0400 Subject: [PATCH 2/8] build: fetch the aforge binary from the release mirror MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The aforge stage pulled `ghcr.io/agent-field/aforge-v2:chat-v2-exec`. That image is not publicly pullable, so `docker compose up --build` — the quick start this repo advertises — could not work outside the org. Replace it with an HTTPS fetch of the published release asset. The stage downloads `aforge-linux-${TARGETARCH}.gz`, gunzips it, and verifies the decompressed binary against `checksums.txt` from the same directory (the release checksums hash the uncompressed binaries) before making it executable. A bad or missing asset fails the build instead of shipping an unverified binary. AFORGE_BASE_URL and AFORGE_VERSION stay overridable so CI or a mirror can serve the same layout elsewhere. The stage reuses python:3.11-slim rather than adding a second base image to the build. Co-Authored-By: Claude Fable 5 --- Dockerfile | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 331d445..65b1e2b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,38 @@ -ARG AFORGE_IMAGE=ghcr.io/agent-field/aforge-v2:chat-v2-exec -FROM ${AFORGE_IMAGE} AS aforge +# AForge CLI — fetched from the public release mirror and verified against the +# release checksums (which hash the *uncompressed* binaries). Both ARGs are +# overridable so CI or a local mirror can serve the same layout elsewhere: +# docker build --build-arg AFORGE_BASE_URL=... --build-arg AFORGE_VERSION=... . +ARG AFORGE_BASE_URL=https://agentfield.ai/downloads/aforge +ARG AFORGE_VERSION=build-9b3ff482de3f + +# Reuses the python:3.11-slim base (debian bookworm) already pulled for the +# builder/runtime stages rather than adding a second base image to the build. +FROM python:3.11-slim AS aforge + +ARG AFORGE_BASE_URL +ARG AFORGE_VERSION +# TARGETARCH is populated by BuildKit; dpkg is the fallback for the legacy +# builder, where the build platform is always the target platform. +ARG TARGETARCH + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /out + +RUN set -eu; \ + arch="${TARGETARCH:-$(dpkg --print-architecture)}"; \ + curl -fsSL "${AFORGE_BASE_URL}/${AFORGE_VERSION}/aforge-linux-${arch}.gz" -o aforge.gz; \ + gunzip -c aforge.gz > aforge; \ + rm aforge.gz; \ + curl -fsSL "${AFORGE_BASE_URL}/${AFORGE_VERSION}/checksums.txt" -o checksums.txt; \ + grep " aforge-linux-${arch}$" checksums.txt \ + | sed "s/ aforge-linux-.*/ aforge/" \ + | sha256sum -c -; \ + rm checksums.txt; \ + chmod +x aforge FROM python:3.11-slim AS builder @@ -59,7 +92,7 @@ RUN mkdir -p /home/contractaf/.config/opencode && \ chown -R contractaf:contractaf /home/contractaf/.config COPY --from=builder /install /usr/local -COPY --from=aforge /aforge /usr/local/bin/aforge +COPY --from=aforge /out/aforge /usr/local/bin/aforge COPY src/ /app/src/ USER contractaf From ca7530e9081f61df5dfbe6f6e797ecbeba0d7ab3 Mon Sep 17 00:00:00 2001 From: Abir Abbas Date: Mon, 17 Aug 2026 11:22:08 -0400 Subject: [PATCH 3/8] build: pin agentfield to the 0.1.129 PyPI release Drop the git-SHA pin. agentfield 0.1.129 is on PyPI and already ships the Python aforge provider (harness/providers/aforge.py, which runs `aforge exec --json -w `) and HarnessConfig.aforge_bin, so the default path this repo now takes is served by a real release. It also means the image build no longer needs a git checkout to install the SDK. Two things stay inert until Agent-Field/agentfield#905 is released: AGENTFIELD_AFORGE_COMMAND is forwarded to the harness subprocess but read by nobody, and the 0.1.129 provider passes no --timeout, so aforge's own 15-minute wall applies. Bump both pins to the #905 release when it exists. Co-Authored-By: Claude Fable 5 --- Dockerfile | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 65b1e2b..badfc28 100644 --- a/Dockerfile +++ b/Dockerfile @@ -51,7 +51,7 @@ COPY pyproject.toml README.md ./ COPY src/ src/ RUN pip install --no-cache-dir --prefix=/install \ - "agentfield @ git+https://github.com/Agent-Field/agentfield.git@bfd34426d1bdec3cbbfa946682a22ef0a1b91503#subdirectory=sdk/python" \ + "agentfield>=0.1.129" \ "pydantic>=2.0" \ "httpx>=0.27" \ "python-dotenv>=1.0" \ diff --git a/pyproject.toml b/pyproject.toml index 0439600..d32f093 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ version = "0.1.0" description = "Legal contract risk analyzer — finds dangerous clauses, proves exploitability" requires-python = ">=3.10" dependencies = [ - "agentfield @ git+https://github.com/Agent-Field/agentfield.git@bfd34426d1bdec3cbbfa946682a22ef0a1b91503#subdirectory=sdk/python", + "agentfield>=0.1.129", "pydantic>=2.0", "fastapi>=0.100", "uvicorn>=0.20", From e85165e5e5e839c62a6474b56e56cd8ec27be2c3 Mon Sep 17 00:00:00 2001 From: Abir Abbas Date: Mon, 17 Aug 2026 11:22:23 -0400 Subject: [PATCH 4/8] chore: add the agentfield-package.yaml install manifest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Contract-AF was the only Agent-Field product node without one, so `af install https://github.com/Agent-Field/contract-af` had nothing to read. Follows the pr-af / SWE-AF shape: config_version v1, entrypoint, node id and default port, and the user-environment contract (OPENROUTER_API_KEY required; control-plane, model and harness overrides optional). dependencies.system names the aforge CLI because `af install` builds a Python venv and does not fetch harness binaries — the installer prints it as a manual step, which is better than failing on the first harness call. The Docker image, which does fetch it, is unaffected. Co-Authored-By: Claude Fable 5 --- agentfield-package.yaml | 58 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 agentfield-package.yaml diff --git a/agentfield-package.yaml b/agentfield-package.yaml new file mode 100644 index 0000000..c249bb9 --- /dev/null +++ b/agentfield-package.yaml @@ -0,0 +1,58 @@ +config_version: v1 # manifest schema version (omit = legacy v0) +name: contract-af +version: 0.1.0 +description: AI-native legal contract risk analyzer — finds dangerous clauses, proves exploitability +author: Agent-Field + +entrypoint: + start: python -m contract_af.app + healthcheck: /health + +agent_node: + node_id: contract-af + default_port: 8004 + +dependencies: + system: + # `af install` builds a Python venv; it does not fetch harness CLIs (the + # Docker image does). Printed as a manual step so a local install says so + # up front instead of failing on the first harness call. + - "aforge (https://agentfield.ai/downloads/aforge) — or set HARNESS_PROVIDER=opencode" + +user_environment: + required: + # Drives both the coding harness (AForge/OpenCode) and the .ai() reasoning + # calls — every phase of the pipeline needs it. + - name: OPENROUTER_API_KEY + description: LLM provider key (OpenRouter) + type: secret + scope: global + optional: + - name: AGENTFIELD_SERVER + description: Control-plane URL + default: http://localhost:8080 + - name: AGENTFIELD_API_KEY + description: Control-plane API key (if auth is enabled) + type: secret + scope: global + - name: NODE_ID + description: Identity this node registers under + default: contract-af + # AForge is the default harness. OpenCode stays installed as the + # configuration-only rollback: set this to `opencode`. + - name: HARNESS_PROVIDER + description: Coding-agent harness provider (aforge | opencode) + default: aforge + - name: HARNESS_MODEL + description: Model the coding harness uses + default: openrouter/moonshotai/kimi-k2.5 + - name: AI_MODEL + description: Model the .ai() reasoning calls use + default: openrouter/moonshotai/kimi-k2.5 + - name: CONTRACT_AF_AFORGE_BIN + description: Path to the aforge binary (defaults to `aforge` on PATH) + - name: CONTRACT_AF_OPENCODE_BIN + description: Path to the opencode binary (defaults to `opencode` on PATH) + - name: CONTRACT_AF_MAX_TURNS + description: Maximum harness iterations per call + default: "50" From 994661aa13e0d01e9d235129d9fef2c9dbfbe61b Mon Sep 17 00:00:00 2001 From: Abir Abbas Date: Mon, 17 Aug 2026 11:22:23 -0400 Subject: [PATCH 5/8] docs: correct the aforge harness switches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The README claimed `AGENTFIELD_AFORGE_COMMAND=do` selects AForge orchestration. No released agentfield SDK reads that variable — 0.1.129's provider always runs `aforge exec` — so the documented switch did nothing. Say what is actually true today: aforge exec is the default, OpenCode is the configuration-only rollback, and CONTRACT_AF_AFORGE_BIN overrides which binary runs (that one is honoured, via HarnessConfig.aforge_bin). Keep AGENTFIELD_AFORGE_COMMAND set but label it reserved until agentfield#905. Also record where the container gets aforge from, since that is now a fetch-and-verify rather than an image pull. Co-Authored-By: Claude Fable 5 --- .env.example | 7 ++++++- README.md | 8 +++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.env.example b/.env.example index f7298e9..23f73c2 100644 --- a/.env.example +++ b/.env.example @@ -4,9 +4,14 @@ OPENROUTER_API_KEY= # Optional: API key required when the control plane enforces auth AGENTFIELD_API_KEY= -# AForge exec is the default. Set HARNESS_PROVIDER=opencode to roll back. +# AForge exec is the default. Set HARNESS_PROVIDER=opencode to roll back — +# OpenCode stays installed in the image. HARNESS_PROVIDER=aforge +# Reserved: forwarded into the harness subprocess environment but not read +# by agentfield 0.1.129, whose aforge provider always runs `aforge exec`. +# It becomes a real switch once Agent-Field/agentfield#905 ships. AGENTFIELD_AFORGE_COMMAND=exec +# Override which aforge binary runs (honoured today via HarnessConfig.aforge_bin). # CONTRACT_AF_AFORGE_BIN=/absolute/path/to/aforge HARNESS_MODEL=openrouter/moonshotai/kimi-k2.5 AI_MODEL=openrouter/moonshotai/kimi-k2.5 diff --git a/README.md b/README.md index 2b5c386..a4abe34 100644 --- a/README.md +++ b/README.md @@ -146,9 +146,11 @@ docker compose up --build Starts AgentField control plane (`http://localhost:8080`) + Contract-AF agent. -AForge `exec` is the default coding harness and is included in the container. -Set `HARNESS_PROVIDER=opencode` to roll back, or set -`AGENTFIELD_AFORGE_COMMAND=do` to explicitly use AForge orchestration. +AForge `exec` is the default coding harness. The image fetches the released +`aforge` binary from `https://agentfield.ai/downloads/aforge` at build time and +verifies it against the release checksums. OpenCode stays installed as the +configuration-only rollback: set `HARNESS_PROVIDER=opencode`. Point +`CONTRACT_AF_AFORGE_BIN` at another binary to override which `aforge` runs. ```bash curl -X POST http://localhost:8080/api/v1/execute/async/contract-af.analyze \ From 85f15c48b2fe5fad968574d3a53646b3e584304b Mon Sep 17 00:00:00 2001 From: Abir Abbas Date: Mon, 17 Aug 2026 11:22:23 -0400 Subject: [PATCH 6/8] test: pin aforge binary override precedence and key forwarding Two behaviours the config exposes but nothing covered: that CONTRACT_AF_AFORGE_BIN beats AFORGE_BIN beats the default, and that the harness subprocess environment carries the OpenRouter key aforge needs to reach the API. Both are what a user hits first when pointing the harness at a non-PATH binary or debugging an auth failure. Co-Authored-By: Claude Fable 5 --- tests/test_config.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/test_config.py b/tests/test_config.py index c8d3c3c..7f90617 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -26,3 +26,24 @@ def test_opencode_remains_an_explicit_rollback(monkeypatch: pytest.MonkeyPatch) monkeypatch.setenv("HARNESS_PROVIDER", "opencode") assert AIIntegrationConfig.from_env().provider == "opencode" + + +def test_aforge_bin_override_precedence(monkeypatch: pytest.MonkeyPatch) -> None: + """CONTRACT_AF_AFORGE_BIN wins over AFORGE_BIN, which wins over the default.""" + monkeypatch.delenv("CONTRACT_AF_AFORGE_BIN", raising=False) + monkeypatch.setenv("AFORGE_BIN", "/opt/aforge/aforge") + + assert AIIntegrationConfig.from_env().aforge_bin == "/opt/aforge/aforge" + + monkeypatch.setenv("CONTRACT_AF_AFORGE_BIN", "/usr/local/bin/aforge") + + assert AIIntegrationConfig.from_env().aforge_bin == "/usr/local/bin/aforge" + + +def test_provider_env_forwards_provider_keys(monkeypatch: pytest.MonkeyPatch) -> None: + """Harness subprocess env carries the LLM key AForge needs to reach OpenRouter.""" + monkeypatch.setenv("OPENROUTER_API_KEY", "sk-test-key") + + env = AIIntegrationConfig.from_env().provider_env() + + assert env["OPENROUTER_API_KEY"] == "sk-test-key" From 45704381dd9432d6356e98d9b8de62eae6e17d30 Mon Sep 17 00:00:00 2001 From: Abir Abbas Date: Mon, 17 Aug 2026 13:13:39 -0400 Subject: [PATCH 7/8] chore: pin aforge to v0.1.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit aforge-v2 cut its first semver release (v0.1.0), so the AFORGE_VERSION default moves off the build- coordinate onto the tag. Bumping the string is what busts the fetch layer's cache, so this is what actually pulls the released binary instead of restoring the stale one. The Dockerfile ARG is the only place this repo writes the coordinate — the compose file and README defer to it. The AgentField SDK pin is deliberately left alone; it bumps on its own release. Co-Authored-By: Claude Fable 5 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index badfc28..2e79fc2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ # overridable so CI or a local mirror can serve the same layout elsewhere: # docker build --build-arg AFORGE_BASE_URL=... --build-arg AFORGE_VERSION=... . ARG AFORGE_BASE_URL=https://agentfield.ai/downloads/aforge -ARG AFORGE_VERSION=build-9b3ff482de3f +ARG AFORGE_VERSION=v0.1.0 # Reuses the python:3.11-slim base (debian bookworm) already pulled for the # builder/runtime stages rather than adding a second base image to the build. From 3b7f727102ad62ecbf5faa1b87e55132a00f59c8 Mon Sep 17 00:00:00 2001 From: Abir Abbas Date: Mon, 17 Aug 2026 21:45:01 -0400 Subject: [PATCH 8/8] chore: pin agentfield>=0.1.130 (aforge default release) 0.1.130 is the release that ships the aforge exec provider path, so the runtime and build pins move up together. AGENTFIELD_AFORGE_COMMAND is a real switch in this release (it selects `aforge exec` vs `aforge do`), so the .env.example note that called it reserved is no longer accurate. Co-Authored-By: Claude Fable 5 --- .env.example | 5 ++--- Dockerfile | 2 +- pyproject.toml | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index 23f73c2..473dae0 100644 --- a/.env.example +++ b/.env.example @@ -7,9 +7,8 @@ AGENTFIELD_API_KEY= # AForge exec is the default. Set HARNESS_PROVIDER=opencode to roll back — # OpenCode stays installed in the image. HARNESS_PROVIDER=aforge -# Reserved: forwarded into the harness subprocess environment but not read -# by agentfield 0.1.129, whose aforge provider always runs `aforge exec`. -# It becomes a real switch once Agent-Field/agentfield#905 ships. +# Which aforge subcommand the SDK runs: `exec` (default, direct one-shot) or +# `do` (routed workflow). Honoured by agentfield >= 0.1.130. AGENTFIELD_AFORGE_COMMAND=exec # Override which aforge binary runs (honoured today via HarnessConfig.aforge_bin). # CONTRACT_AF_AFORGE_BIN=/absolute/path/to/aforge diff --git a/Dockerfile b/Dockerfile index 2e79fc2..4d8890c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -51,7 +51,7 @@ COPY pyproject.toml README.md ./ COPY src/ src/ RUN pip install --no-cache-dir --prefix=/install \ - "agentfield>=0.1.129" \ + "agentfield>=0.1.130" \ "pydantic>=2.0" \ "httpx>=0.27" \ "python-dotenv>=1.0" \ diff --git a/pyproject.toml b/pyproject.toml index d32f093..9bde38d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ version = "0.1.0" description = "Legal contract risk analyzer — finds dangerous clauses, proves exploitability" requires-python = ">=3.10" dependencies = [ - "agentfield>=0.1.129", + "agentfield>=0.1.130", "pydantic>=2.0", "fastapi>=0.100", "uvicorn>=0.20",