You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -202,43 +201,6 @@ The AW Harness is the topmost layer within the gh-aw container. The following AS
202
201
203
202
9.**Observable.** All implementations **MUST** emit a JSONL event stream to stderr and **SHOULD** generate OTel spans when an OTLP endpoint is configured.
204
203
205
-
### 4.3 Pi SDK and OpenClaw Extension Format Compatibility
206
-
207
-
*(This section is non-normative.)*
208
-
209
-
The AW Harness uses Pi SDK's `ExtensionAPI` as its native extension mechanism. OpenClaw (a separate open-source agent runtime at `openclaw/openclaw`) uses a structurally similar but distinct plugin API (`OpenClawPluginApi`). This section documents the relationship between the two APIs and the compatibility requirements that apply.
210
-
211
-
#### 4.3.1 API Surface Comparison
212
-
213
-
| Pi SDK (`ExtensionAPI`) | OpenClaw (`OpenClawPluginApi`) | Notes |
|`pi.on(event, handler)`|`api.on(hookName, handler, opts?)`| Event names differ between the two runtimes (e.g., Pi `"turn_end"` vs. OpenClaw `"after_agent_turn"`) |
|`(no direct equivalent)`|`api.registerAgentHarness(...)`| OpenClaw's experimental low-level agent executor seam; Pi SDK exposes the session directly instead |
219
-
|`(lifecycle via pi.on)`|`api.registerHook(events, handler)`| OpenClaw has a separate lifecycle hook registry distinct from its agent event hooks |
220
-
|`(no equivalent)`|`api.registerSessionExtension(...)`| OpenClaw-specific: plugin-owned session state projected through Gateway sessions |
221
-
222
-
#### 4.3.2 Manifest Requirements (OpenClaw Only)
223
-
224
-
OpenClaw plugins **MUST** ship an `openclaw.plugin.json` manifest in the plugin root. Pi SDK does not use a manifest file; extensions are registered programmatically. The two formats are **not interchangeable**:
225
-
226
-
- A Pi extension is a TypeScript function `(pi: ExtensionAPI) => void`.
227
-
- An OpenClaw plugin is a package exporting `definePluginEntry({ id, name, description, register(api) { ... } })` with an accompanying `openclaw.plugin.json`.
228
-
229
-
#### 4.3.3 Compatibility Requirements
230
-
231
-
The gh-aw extensions in this specification target Pi SDK only. However, to facilitate future portability to OpenClaw:
232
-
233
-
- Extensions **SHOULD** keep Pi SDK dependencies isolated to the entry function boundary rather than scattered across extension modules.
234
-
- Tool definitions (name, description, parameter schema, and `execute` function) **SHOULD** be expressed as plain objects so they can be adapted to either `pi.registerTool()` or `api.registerTool()` without rewriting tool logic.
235
-
- Event handler functions **SHOULD** treat the event source (Pi `"turn_end"` vs. OpenClaw `"after_agent_turn"`) as a configuration layer, not embedded constants, to ease future porting.
236
-
- Extensions **MUST NOT** use Pi-internal APIs that have no OpenClaw equivalent (e.g., direct `AgentSession` handle manipulation outside the `ExtensionAPI` surface).
237
-
238
-
#### 4.3.4 `registerAgentHarness` Consideration
239
-
240
-
OpenClaw exposes an experimental `api.registerAgentHarness(...)` method that provides a low-level agent executor seam. This seam could in principle host the AW Harness loop within an OpenClaw gateway. The gh-aw aw harness **does not** require or target this seam; it runs standalone via Pi SDK. If a future integration with OpenClaw's gateway is desired, `registerAgentHarness` is the appropriate OpenClaw extension point to evaluate at that time.
241
-
242
204
---
243
205
244
206
## 5. Harness Invocation Contract
@@ -353,6 +315,11 @@ An `engine: aw` workflow document **MUST** include a YAML frontmatter block conf
353
315
> time-critical-minutes: 2
354
316
> budget-warn-percent: 75
355
317
> budget-critical-percent: 90
318
+
>
319
+
> # Optional: Pi SDK-compatible extensions to load alongside built-in gh-aw extensions.
320
+
> # Each entry is a repo-relative path to a compiled .cjs file or an npm package name.
321
+
> extensions:
322
+
> - ./extensions/custom-tool.cjs
356
323
> ---
357
324
>
358
325
> Review all changes pushed to the default branch in the last 24 hours.
@@ -384,7 +351,55 @@ The `harness.steering` key is **OPTIONAL**. When present, it **MAY** contain:
384
351
- `budget-warn-percent` (number): Budget percentage at which a warning **SHOULD** be injected. Default: `75`.
385
352
- `budget-critical-percent` (number): Budget percentage at which the session **MUST** be aborted. Default: `90`.
386
353
387
-
#### 6.1.4 `imports:`
354
+
#### 6.1.4 `harness.extensions`
355
+
356
+
The `harness.extensions` key is **OPTIONAL**. When present, it **MUST** be a list of Pi SDK-compatible extension references that the harness loads and registers into the `AgentSession` at runtime, in addition to the built-in gh-aw extensions.
357
+
358
+
Each entry is a string in one of the following forms:
359
+
360
+
- **Repository-relative path** — a path starting with `./` or `../` pointing to a compiled CommonJS file (`.cjs`) co-located with the workflow (e.g., `./extensions/my-tool.cjs`).
361
+
- **npm package name** — a bare or scoped npm package name (e.g., `@my-org/my-pi-extension`) that is available in the container `node_modules` at runtime.
362
+
363
+
Each referenced module **MUST** export a default function with the Pi SDK `ExtensionAPI` signature:
- Dynamically load each extension using `require()` (for local paths) or `require()` / `import()` (for npm packages).
372
+
- Register each user extension into the `AgentSession` alongside the built-in gh-aw extensions, after all built-in extensions have been registered.
373
+
- Emit a warning to stderr if an extension fails to load, and **MUST NOT** abort the session for a failed user extension unless `harness.extensions-required: true` is set.
374
+
375
+
A conforming implementation **MUST NOT** allow user extensions to override or replace the built-in gh-aw extensions. User extensions run after all built-in extensions and **MUST NOT** be able to unregister or intercept built-in extension behavior.
376
+
377
+
> [!NOTE] Non-normative example.
378
+
>
379
+
> ```yaml
380
+
> harness:
381
+
> budget:
382
+
> max-cost-usd: 5.00
383
+
> extensions:
384
+
> - ./extensions/custom-tool.cjs # Local compiled extension
The `imports:` key is **OPTIONAL**. It is a standard gh-aw frontmatter key that lists the paths of files whose contents **MUST** be resolved by the compiler and made available to the harness as part of the compiled inputs.
390
405
@@ -434,7 +449,7 @@ A conforming implementation **MUST** source every item included in the session's
434
449
435
450
- The Markdown body from `prompt.txt` (loaded per [Section 6.3](#63-prompt-loading)).
436
451
- The `harness.system` prompt if declared in the `harness:` frontmatter block.
437
-
- Files, skills, and sub-workflows declared via the `imports:` frontmatter key (see [Section 6.1.4](#614-imports)) and resolved by the compiler into inputs passed at invocation time.
452
+
- Files, skills, and sub-workflows declared via the `imports:` frontmatter key (see [Section 6.1.5](#615-imports)) and resolved by the compiler into inputs passed at invocation time.
438
453
439
454
A conforming implementation **MUST NOT** automatically load AGENTS.md files, `.github/agents/` entries, skills directories, or any other ambient repository files unless they are explicitly listed in `imports:`. This behavior is a deliberate divergence from engines such as `engine: copilot` that inject ambient context automatically.
440
455
@@ -470,13 +485,18 @@ A conforming implementation **MUST** execute the workflow as follows:
> ...userExtensions, // User extensions run after built-in extensions
480
500
> ];
481
501
>
482
502
> const { session } = await createAgentSession({
@@ -493,7 +513,7 @@ A conforming implementation **MUST** execute the workflow as follows:
493
513
494
514
1. The implementation **MUST** invoke `createAgentSession()` exactly once per harness invocation.
495
515
2. The prompt passed to `session.prompt()` **MUST** be the full contents of `prompt.txt` as loaded per [Section 6.3](#63-prompt-loading).
496
-
3. The implementation **MUST** load all six gh-aw Pi extensions (see [Section 8](#8-extensions)) into the session.
516
+
3. The implementation **MUST** load all six gh-aw Pi extensions (see [Section 8](#8-extensions)) into the session. If `harness.extensions` is declared in the configuration, the implementation **MUST** also load each user-declared extension after the built-in extensions (see [Section 6.1.4](#614-harness-extensions)).
497
517
4. After the session completes (success or failure), the implementation **MUST** call `session.dispose()`.
498
518
5. If the budget gate has been triggered (via the cost-tracker extension), the implementation **MUST** exit with code `1`.
499
519
@@ -506,6 +526,7 @@ A conforming implementation **MUST** execute the workflow as follows:
506
526
- Safe-output tools registered
507
527
- Steering, repair, cost, observability extensions active
508
528
(MCP tools available as bash CLI commands via cli-proxy — no bridging needed)
529
+
- User extensions (from harness.extensions) loaded and registered after built-ins
509
530
3. session.prompt(promptText) → Pi agent loop runs
@@ -515,7 +536,7 @@ A conforming implementation **MUST** execute the workflow as follows:
515
536
516
537
## 8. Extensions
517
538
518
-
All gh-aw-specific behavior **MUST** be packaged as Pi extensions. Each extension **MUST** be a standalone TypeScript module that exports a default function with signature `(pi: ExtensionAPI) => void | Promise<void>`. For compatibility guidance between Pi's `ExtensionAPI` and OpenClaw's `OpenClawPluginApi`, see [§4.3](#43-pi-sdk-and-openclaw-extension-format-compatibility).
539
+
All gh-aw-specific behavior **MUST** be packaged as Pi extensions. Each extension **MUST** be a standalone TypeScript module that exports a default function with signature `(pi: ExtensionAPI) => void | Promise<void>`.
519
540
520
541
The following six extensions **MUST** be loaded into the `AgentSession` created by the harness.
521
542
@@ -987,6 +1008,8 @@ The following ordered work items describe the implementation sequence:
987
1008
988
1009
5.**Implement entry point** — Create a single `createAgentSession()` with gh-aw extensions loaded. Pass `prompt.txt` contents as the prompt. Dispose session on completion.
989
1010
1011
+
5a. **Implement user extension loader** — Read `harness.extensions` from `config.json`. For each entry: resolve repository-relative paths from the harness working directory; load npm package names via `require()`. Verify each loaded module exports a default function of type `(pi: ExtensionAPI) => void`. Emit a stderr warning for each failed load; abort only if `harness.extensions-required: true` is set. Append loaded extensions to the session extension list after built-ins.
1012
+
990
1013
6.**Implement context engine** — Prompt assembly with priority ordering. Compaction via `none`, `sliding-window`, or `summarize`.
991
1014
992
1015
7.**Implement cost tracker extension** — Pi extension that monitors `turn_end` events for token/cost data. Enforces soft (steer warning) and hard (abort) budget gates.
@@ -1018,6 +1041,8 @@ The following ordered work items describe the implementation sequence:
1018
1041
1019
1042
**Safe outputs isolation.** The safe-outputs extension **MUST NOT** perform live GitHub API calls during agent execution. All GitHub mutations **MUST** be expressed as artifact files processed by the post-agent job, which applies threat detection and validation before acting.
1020
1043
1044
+
**User extension isolation.** Extensions declared via `harness.extensions` run inside the same Node.js process as the built-in extensions. A conforming implementation **MUST NOT** execute user extensions with elevated privileges. Extension authors are responsible for ensuring that their extensions do not exfiltrate credentials or subvert built-in budget or safe-outputs behavior. Workflow authors are responsible for auditing third-party npm extension packages before referencing them in `harness.extensions`.
1045
+
1021
1046
**Budget enforcement.** The cost-tracker extension provides a hard budget gate. A conforming implementation **MUST** abort the session if the cost exceeds the configured maximum, preventing runaway spending from misbehaving agents.
1022
1047
1023
1048
**Token and secret handling.** Provider credentials (e.g., `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GITHUB_TOKEN`) **MUST NOT** be logged to stderr or embedded in JSONL events. Implementations **MUST** treat all credential env vars as opaque secrets.
@@ -1064,6 +1089,3 @@ OpenTelemetry specification for distributed tracing. <https://opentelemetry.io/d
1064
1089
1065
1090
**[gh-aw]**
1066
1091
GitHub Agentic Workflows — the gh-aw CLI extension that compiles Markdown workflow files to GitHub Actions YAML. <https://github.com/github/gh-aw>
1067
-
1068
-
**[OpenClaw]**
1069
-
OpenClaw — open-source agent runtime with a plugin SDK (`OpenClawPluginApi`) that is structurally related to but distinct from Pi SDK's `ExtensionAPI`. See §4.3 for API compatibility notes. <https://github.com/openclaw/openclaw>
0 commit comments