external-subagent 0.1.5 → 0.3.0

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.
package/README.md CHANGED
@@ -8,10 +8,10 @@ independent axes:
8
8
  - **Hosts** — Codex (`install-plugin codex` or `install-mcp`), ZCode
9
9
  (`install-plugin zcode`), and any custom local MCP client that connects
10
10
  directly to the facade without registration.
11
- - **Subagents** — ZCode, DeepSeek Harness (DSH), and Codex, each routed
12
- through an internal adapter and subject to the per-subagent limitations
13
- listed in [docs/product.md](docs/product.md) and
14
- [docs/mcp-api.md](docs/mcp-api.md).
11
+ - **Subagents** — ZCode, DeepSeek Harness (DSH), Codex, and Google
12
+ Antigravity (`agy`), each routed through an internal adapter and subject to
13
+ the per-subagent limitations listed in [docs/product.md](docs/product.md)
14
+ and [docs/mcp-api.md](docs/mcp-api.md).
15
15
 
16
16
  ## Status
17
17
 
@@ -26,9 +26,9 @@ artifact and explicitly initializing to a launchd-resident service
26
26
  active-task upgrade and standalone initialization are implemented and
27
27
  reviewed.
28
28
 
29
- All three subagents are **disabled by default** and are enabled per name with
30
- `external-subagent agents enable <zcode|dsh|codex>`: a successful local probe
31
- writes the configuration (no write on failure), and `dsh`/`codex` need a
29
+ All four subagents are **disabled by default** and are enabled per name with
30
+ `external-subagent agents enable <zcode|dsh|codex|agy>`: a successful local probe
31
+ writes the configuration (no write on failure), and `dsh`/`codex`/`agy` need a
32
32
  daemon restart to take effect. ZCode admits all four permission modes
33
33
  (build/edit/plan/yolo) and rejects an explicit spawn `model`; DSH admits
34
34
  `build` and strict `plan`, with model selection as explicit spawn model,
@@ -40,9 +40,16 @@ legacy build composition and `plan` still requires an empty manifest); Codex
40
40
  admits all four modes
41
41
  (build/edit → workspace-write, plan → read-only, yolo → danger-full-access,
42
42
  all pinning `approvalPolicy=never`) and rejects a non-empty `write_manifest`
43
- with `codex_write_manifest_unsupported`. `observe` works on all three: ZCode
43
+ with `codex_write_manifest_unsupported`; Antigravity (`agy`) spawns only when
44
+ its `enabled + spawn_supported` gate and an absolute `AGY_RUNTIME_PATH`
45
+ executable admit it, runs with `build` (`--mode accept-edits`) or `yolo`
46
+ (`--dangerously-skip-permissions`), selects a catalog-validated bare model
47
+ slug, admits effort from `low|medium|high|max`, and rejects a non-empty
48
+ `write_manifest` with `agy_write_manifest_unsupported` (it has no
49
+ permission-respond interaction — tools are soft-denied and denied actions
50
+ surface on failure diagnostics). `observe` works on all four: ZCode
44
51
  and DSH expose the public reasoning tail (at most 200 characters) and Codex
45
- reports `reasoning: null`.
52
+ and agy report `reasoning: null`.
46
53
 
47
54
  The daemon socket environment variable is now the neutral
48
55
  `EXTERNAL_SUBAGENT_SOCKET`, with no fallback to the retired name. An existing
@@ -65,7 +65,7 @@ export function parseSubagentsArgs(args) {
65
65
  const [operation, ...rest] = args;
66
66
  if (!['list', 'status', 'probe', 'models', 'enable'].includes(operation)) throw new CliError('INVALID_ARGUMENT', `unsupported subagents operation: ${operation}`, 2);
67
67
  if (operation === 'enable') {
68
- if (rest.length !== 1 || !SUBAGENT_IDS.includes(rest[0])) throw new CliError('INVALID_ARGUMENT', 'usage: agents enable <zcode|dsh|codex>', 2);
68
+ if (rest.length !== 1 || !SUBAGENT_IDS.includes(rest[0])) throw new CliError('INVALID_ARGUMENT', 'usage: agents enable <zcode|dsh|codex|agy>', 2);
69
69
  return { operation, subagent: rest[0] };
70
70
  }
71
71
  if (operation === 'probe') return parseProbeArgs(rest);
@@ -82,7 +82,7 @@ export async function subagentsCommand(paths, input = {}, options = {}) {
82
82
  if (operation === 'enable') {
83
83
  const agent = input.subagent;
84
84
  if (!SUBAGENT_IDS.includes(agent) || ['through', 'workspace', 'home'].some((key) => input[key] !== undefined)) {
85
- throw new CliError('INVALID_ARGUMENT', 'usage: agents enable <zcode|dsh|codex>', 2);
85
+ throw new CliError('INVALID_ARGUMENT', 'usage: agents enable <zcode|dsh|codex|agy>', 2);
86
86
  }
87
87
  if (typeof options.callDaemon !== 'function' || typeof options.socket !== 'string') throw new CliError('INTERNAL_ERROR', 'agents enable requires a daemon connection');
88
88
  const entry = config.subagents[agent];
@@ -102,9 +102,15 @@ export async function subagentsCommand(paths, input = {}, options = {}) {
102
102
  if (typeof local.runtime_path !== 'string' || !path.isAbsolute(local.runtime_path) || typeof local.version !== 'string' || !local.version.trim()) {
103
103
  throw new CliError('agent_probe_failed', 'Probe did not return an absolute runtime_path and observed version', 2);
104
104
  }
105
- const home = local.scope?.home;
106
- if (typeof home !== 'string' || !path.isAbsolute(home)) throw new CliError('agent_probe_failed', `Cannot enable ${agent}: configure subagents.${agent}.home or export ${agent.toUpperCase()}_HOME before starting the daemon`, 2);
107
- Object.assign(patch, { runtime_path: local.runtime_path, home, profile: agent === 'dsh' ? 'acp' : (entry.profile ?? null), version: local.version });
105
+ if (agent === 'agy') {
106
+ // agy has no home override: the daemon resolves the executable from
107
+ // AGY_RUNTIME_PATH, so the patch carries runtime_path + version only.
108
+ Object.assign(patch, { runtime_path: local.runtime_path, version: local.version });
109
+ } else {
110
+ const home = local.scope?.home;
111
+ if (typeof home !== 'string' || !path.isAbsolute(home)) throw new CliError('agent_probe_failed', `Cannot enable ${agent}: configure subagents.${agent}.home or export ${agent.toUpperCase()}_HOME before starting the daemon`, 2);
112
+ Object.assign(patch, { runtime_path: local.runtime_path, home, profile: agent === 'dsh' ? 'acp' : (entry.profile ?? null), version: local.version });
113
+ }
108
114
  }
109
115
  const updated = updateConfig(paths.config, (latest) => {
110
116
  if (Object.entries(patch).every(([key, value]) => latest.subagents[agent][key] === value)) return latest;
@@ -1,7 +1,7 @@
1
1
  import { CliError } from '../errors.mjs';
2
2
 
3
3
  export const CONFIG_SCHEMA_VERSION = 2;
4
- export const SUBAGENT_IDS = Object.freeze(['zcode', 'dsh', 'codex']);
4
+ export const SUBAGENT_IDS = Object.freeze(['zcode', 'dsh', 'codex', 'agy']);
5
5
  const CONFIG_FIELDS = new Set(['schema_version', 'revision', 'default_subagent', 'subagents']);
6
6
  const AGENT_FIELDS = new Set(['enabled', 'spawn_supported', 'default_model', 'runtime_path', 'home', 'profile', 'version']);
7
7
 
@@ -24,6 +24,7 @@ export function defaultConfig() {
24
24
  zcode: { enabled: false, spawn_supported: false, default_model: null },
25
25
  dsh: { enabled: false, spawn_supported: false, default_model: null, runtime_path: null, home: null, profile: null, version: null },
26
26
  codex: { enabled: false, spawn_supported: false, default_model: null, runtime_path: null, home: null, profile: null, version: null },
27
+ agy: { enabled: false, spawn_supported: false, default_model: null, runtime_path: null, home: null, profile: null, version: null },
27
28
  },
28
29
  };
29
30
  }
package/cli/constants.mjs CHANGED
@@ -8,7 +8,7 @@ const IS_DEBUG_VARIANT = process.env.EXTERNAL_SUBAGENT_VARIANT === 'debug';
8
8
 
9
9
  export const PRODUCT_NAME = IS_DEBUG_VARIANT ? 'external-subagent-debug' : 'external-subagent';
10
10
  export const PRODUCT_ID = IS_DEBUG_VARIANT ? 'external_subagent_debug' : 'external_subagent';
11
- export const VERSION = '0.1.5';
11
+ export const VERSION = '0.3.0';
12
12
  export const LAUNCH_AGENT_LABEL = IS_DEBUG_VARIANT ? 'com.external-subagent-debug.daemon' : 'com.external-subagent.daemon';
13
13
  export const DAEMON_BIN_NAME = IS_DEBUG_VARIANT ? 'external-subagent-debugd' : 'external-subagentd';
14
14
  export const MCP_BIN_NAME = IS_DEBUG_VARIANT ? 'external-subagent-debug-mcp' : 'external-subagent-mcp';
@@ -21,7 +21,7 @@ function escapeXml(value) {
21
21
  // Presence is diagnostic only; enabling is an explicit probe + config operation.
22
22
  export function runtimeObservations(paths, options = {}) {
23
23
  const config = readConfig(paths.config);
24
- return Object.fromEntries(['zcode', 'dsh', 'codex'].map((agent) => {
24
+ return Object.fromEntries(['zcode', 'dsh', 'codex', 'agy'].map((agent) => {
25
25
  const runtime = agent === 'zcode' ? (options.zcodeRuntime ?? ZCODE_RUNTIME) : config.subagents[agent].runtime_path;
26
26
  return [agent, { path: runtime, present: Boolean(runtime && fs.existsSync(runtime)), enabled: config.subagents[agent].enabled }];
27
27
  }));
@@ -35,6 +35,7 @@ export function launchAgentPlist(paths, options = {}) {
35
35
  const config = readConfig(paths.config);
36
36
  const { runtime_path: dshRuntime, home: dshHome, profile: dshProfile, version: dshVersion } = config.subagents.dsh;
37
37
  const { runtime_path: codexRuntime, home: codexHome } = config.subagents.codex;
38
+ const { runtime_path: agyRuntime } = config.subagents.agy;
38
39
  const configRevision = config.revision;
39
40
  // AUD-005/D1: the standalone service never depends on an unrelated runtime.
40
41
  // The pinned ZCode runtime is forwarded only when that installation exists;
@@ -70,6 +71,10 @@ export function launchAgentPlist(paths, options = {}) {
70
71
  // fails Codex admission closed instead of falling back to ~/.codex.
71
72
  ...(codexRuntime ? [`<key>CODEX_RUNTIME_PATH</key><string>${escapeXml(codexRuntime)}</string>`] : []),
72
73
  ...(codexHome ? [`<key>CODEX_HOME</key><string>${escapeXml(codexHome)}</string>`] : []),
74
+ // agy has no home override: only its persisted executable is forwarded, so
75
+ // the service-side daemon resolves the same AGY_RUNTIME_PATH the
76
+ // interactive one does.
77
+ ...(agyRuntime ? [`<key>AGY_RUNTIME_PATH</key><string>${escapeXml(agyRuntime)}</string>`] : []),
73
78
  ].join('');
74
79
  return Buffer.from(`<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n<plist version="1.0"><dict>\n<key>Label</key><string>${LAUNCH_AGENT_LABEL}</string>\n<key>ProgramArguments</key><array>${programArguments.join('')}</array>\n<key>EnvironmentVariables</key><dict>${dshEnvironment}</dict>\n<key>RunAtLoad</key><true/><key>KeepAlive</key><true/>\n<key>StandardOutPath</key><string>${escapeXml(path.join(paths.logs, 'daemon.log'))}</string>\n<key>StandardErrorPath</key><string>${escapeXml(path.join(paths.logs, 'daemon-error.log'))}</string>\n</dict></plist>\n`);
75
80
  }
package/cli/rpc.mjs CHANGED
@@ -174,6 +174,16 @@ function publicTask(task) {
174
174
  };
175
175
  }
176
176
 
177
+ // The wait response carries only the task lifecycle header: admission
178
+ // provenance never changes after spawn, so wait does not repeat it.
179
+ function publicTaskHeader(task) {
180
+ return {
181
+ agent_id: publicTaskId(task.agent_id),
182
+ status: task.status,
183
+ session_id: task.session_id ?? null,
184
+ };
185
+ }
186
+
177
187
  function publicResult(result) {
178
188
  if (result == null) return null;
179
189
  return {
@@ -198,7 +208,7 @@ export function projectDaemonResult(command, result) {
198
208
  return { agent_id: publicTaskId(result.task.agent_id), status: result.task.status };
199
209
  case 'wait': {
200
210
  const { result: taskResult, task, activity, kind: _kind, ...rest } = result;
201
- return { ...rest, task: publicTask(task), activity, result: publicResult(taskResult) };
211
+ return { ...rest, task: publicTaskHeader(task), activity, result: publicResult(taskResult) };
202
212
  }
203
213
  case 'list': return { tasks: result.tasks.map(publicTask), next_cursor: result.next_cursor ?? null };
204
214
  case 'send': return { message_id: result.message_id, disposition: result.disposition };
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "schema_version": 1,
3
3
  "product": "external-subagent",
4
- "version": "0.1.5",
4
+ "version": "0.3.0",
5
5
  "platform": "darwin-arm64",
6
6
  "files": [
7
7
  {
8
8
  "name": "external-subagentd",
9
- "bytes": 9443072,
9
+ "bytes": 9771664,
10
10
  "mode": "755",
11
- "sha256": "1c6048c4202733b81a5b80cab82bee3a0a7071f90341f8bf2948707bf794e067"
11
+ "sha256": "b7e34283d40d91f5e210f6b91884a1fbfd4291a3454a1127d45c83566edb9b93"
12
12
  },
13
13
  {
14
14
  "name": "external-subagent-mcp",
15
15
  "bytes": 937840,
16
16
  "mode": "755",
17
- "sha256": "07f4d3949165419fba81c66ef4fd631615490a13dcf8b12a1c6859762e0396af"
17
+ "sha256": "2f811110d1acf479ddfe62a5f00913e7d38cbe7a58d51c7c14c4ab6fa5a08247"
18
18
  }
19
19
  ]
20
20
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "external-subagent",
3
- "version": "0.1.5",
4
- "description": "Manage bounded ZCode, DeepSeek Harness (DSH), and Codex subagent tasks through a local MCP service for any local host (Codex, ZCode, or a custom MCP client)",
3
+ "version": "0.3.0",
4
+ "description": "Manage bounded ZCode, DeepSeek Harness (DSH), Codex, and Google Antigravity (agy) subagent tasks through a local MCP service for any local host (Codex, ZCode, or a custom MCP client)",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -7,7 +7,7 @@ description: Manage bounded repository-scoped tasks through external-subagent.
7
7
 
8
8
  Use the `external_subagent_*` tools to inspect status, spawn a task with an explicit
9
9
  `subagent`, wait for progress, retrieve the complete result, and close the task.
10
- Execution targets are `zcode`, `dsh`, and `codex`; each name currently has one
10
+ Execution targets are `zcode`, `dsh`, `codex`, and `agy`; each name currently has one
11
11
  runtime instance and no instance selector is supported. Omitting `subagent` uses
12
12
  `default_subagent` or returns `subagent_required`; unknown targets return
13
13
  `subagent_unknown`, and unknown spawn fields are rejected before dispatch.
@@ -22,10 +22,11 @@ evidence are operator diagnostics — read them with the CLI `diagnose` command
22
22
  instead of the MCP status tool.
23
23
 
24
24
  Spawn accepts an optional `effort` token that steers the task's reasoning
25
- effort. Omit it to keep each agent's current default (codex keeps its existing
26
- wire default; zcode and dsh send no effort field or call at all). `codex`
27
- admits only the closed set
25
+ effort. Omit it to keep each agent's current default (codex and agy keep their
26
+ existing wire default; zcode and dsh send no effort field or call at all).
27
+ `codex` admits only the closed set
28
28
  `low | medium | high | xhigh | max` — `minimal` and `ultra` are rejected;
29
+ `agy` admits only the measured closed set `low | medium | high | max`;
29
30
  `zcode` and `dsh` accept any bounded token (1..24 bytes of `[a-z0-9_]`) and
30
31
  pass it through to the runtime, because the supported set is only known at
31
32
  runtime. A malformed or unsupported token is rejected before dispatch, so no
@@ -40,9 +41,9 @@ Codex home instances, and offers plugin or direct MCP bindings; built-in
40
41
  dirs with a single per-user instance. This is separate
41
42
  from `subagent.codex`. Protocol implementations are adapters.
42
43
 
43
- All three subagents (`zcode`, `dsh`, `codex`) are disabled by default; enable one
44
+ All four subagents (`zcode`, `dsh`, `codex`, `agy`) are disabled by default; enable one
44
45
  with `external-subagent agents enable <name>`, which runs a local probe and writes
45
- the configuration only on success (a daemon restart is required for `dsh`/`codex`).
46
+ the configuration only on success (a daemon restart is required for `dsh`/`codex`/`agy`).
46
47
  Actual per-subagent limitations (from the accepted code):
47
48
 
48
49
  - `zcode` — disabled until explicitly enabled; all four permission modes
@@ -56,7 +57,15 @@ Actual per-subagent limitations (from the accepted code):
56
57
  and `yolo` to sandbox=danger-full-access, all pinning approvalPolicy=never.
57
58
  A non-empty spawn `write_manifest` is rejected before task creation with
58
59
  `codex_write_manifest_unsupported`.
59
- - `observe` — available for all three subagents; `zcode` and `dsh` return the
60
- public reasoning tail (at most 200 characters), while `codex` does not collect
61
- reasoning and returns `reasoning: null`. Tool history and coverage are reported
62
- truthfully per adapter capability.
60
+ - `agy` (Google Antigravity) — disabled until explicitly enabled with an
61
+ absolute executable `AGY_RUNTIME_PATH`; only `build` (`--mode accept-edits`)
62
+ and `yolo` (`--dangerously-skip-permissions`) are admitted (plan/edit are
63
+ rejected with `agy_permission_mode_unsupported`); `model` is a bare slug
64
+ validated against the `agy models` catalog; a non-empty spawn
65
+ `write_manifest` is rejected before task creation with
66
+ `agy_write_manifest_unsupported`; there is no permission-respond interaction
67
+ (tools are soft-denied).
68
+ - `observe` — available for all four subagents; `zcode` and `dsh` return the
69
+ public reasoning tail (at most 200 characters), while `codex` and `agy` do not
70
+ collect reasoning and return `reasoning: null`. Tool history and coverage are
71
+ reported truthfully per adapter capability.
@@ -15,7 +15,7 @@
15
15
  "type": "object",
16
16
  "required": ["subagent", "configured", "enabled", "spawn_supported", "permission_modes", "model_selection", "effort_selection", "local", "auth", "hi"],
17
17
  "properties": {
18
- "subagent": { "enum": ["zcode", "dsh", "codex"] },
18
+ "subagent": { "enum": ["zcode", "dsh", "codex", "agy"] },
19
19
  "configured": { "type": "boolean" },
20
20
  "enabled": { "type": "boolean" },
21
21
  "spawn_supported": { "type": "boolean" },
@@ -64,17 +64,24 @@
64
64
  "properties": {
65
65
  "subagent": { "type": "string", "minLength": 1, "description": "Subagent route key; omission uses configured default_subagent or returns subagent_required. Null is invalid; dsh production spawn requires its enabled + spawn_supported + pinned-runtime configuration." },
66
66
  "repository": { "type": "string", "minLength": 1 },
67
- "permission_mode": { "$ref": "#/properties/permission_mode", "description": "codex supports build/edit (workspace-write), plan (read-only), and yolo (danger-full-access), always with approvalPolicy=never." },
67
+ "permission_mode": { "$ref": "#/properties/permission_mode", "description": "codex supports build/edit (workspace-write), plan (read-only), and yolo (danger-full-access), always with approvalPolicy=never; agy supports only build (--mode accept-edits) and yolo (--dangerously-skip-permissions)." },
68
68
  "prompt": { "type": "string", "minLength": 1 },
69
- "model": { "type": "string", "minLength": 1, "description": "Task model. dsh requires provider:model, split at the first colon (the model side may contain further colons; a missing colon or an empty side is rejected before any task). codex uses its own model id; zcode rejects model selection." },
70
- "effort": { "type": "string", "minLength": 1, "maxLength": 24, "pattern": "^[a-z0-9_]+$", "description": "Reasoning-effort token: 1..24 bytes of [a-z0-9_]. codex admits only low, medium, high or xhigh; zcode and dsh pass the bounded token through. Omission keeps the runtime default." },
71
- "write_manifest": { "type": "array", "items": { "type": "string", "minLength": 1 }, "description": "codex requires an empty or omitted write_manifest; non-empty input returns codex_write_manifest_unsupported before task creation. dsh admits a non-empty manifest in build through the guarded manifest-build composition (workspace-write sandbox, only tool-fs writable, out-of-manifest paths rejected as FS_WRITE_MANIFEST_DENIED), at most 256 entries; an explicit [\".\"] keeps the existing build composition. plan requires an empty manifest for every subagent." }
69
+ "model": { "type": "string", "minLength": 1, "description": "Task model. dsh requires provider:model, split at the first colon (the model side may contain further colons; a missing colon or an empty side is rejected before any task). codex uses its own model id; zcode uses provider/model (a bare token keeps its backward-compatible zai/<token> reading). agy uses a bare model slug with no ':' or '/' separator or whitespace; admission validates only that shape and the daemon does not verify catalog membership, so an unknown slug fails loudly at session start when the agy CLI rejects it. Omission falls back to the configured default_model for dsh, zcode and agy, then to the provider-native model; codex requires an explicit model or agents.codex.default_model and never falls back to a provider default." },
70
+ "effort": { "type": "string", "minLength": 1, "maxLength": 24, "pattern": "^[a-z0-9_]+$", "description": "Reasoning-effort token: 1..24 bytes of [a-z0-9_]. codex admits only low, medium, high or xhigh; agy admits only low, medium, high or max; zcode and dsh pass the bounded token through. Omission keeps the runtime default." },
71
+ "write_manifest": { "type": "array", "items": { "type": "string", "minLength": 1 }, "description": "codex requires an empty or omitted write_manifest; non-empty input returns codex_write_manifest_unsupported before task creation. agy likewise requires an empty or omitted write_manifest; non-empty input returns agy_write_manifest_unsupported before task creation. dsh admits a non-empty manifest in build through the guarded manifest-build composition (workspace-write sandbox, only tool-fs writable, out-of-manifest paths rejected as FS_WRITE_MANIFEST_DENIED), at most 256 entries; an explicit [\".\"] keeps the existing build composition. plan requires an empty manifest for every subagent." }
72
72
  },
73
73
  "allOf": [
74
74
  { "if": { "required": ["subagent"], "properties": { "subagent": { "const": "codex" } } },
75
75
  "then": { "properties": { "write_manifest": { "maxItems": 0 } } } },
76
76
  { "if": { "required": ["subagent"], "properties": { "subagent": { "const": "dsh" } } },
77
77
  "then": { "properties": { "write_manifest": { "maxItems": 256 } } } },
78
+ { "if": { "required": ["subagent"], "properties": { "subagent": { "const": "agy" } } },
79
+ "then": { "properties": {
80
+ "permission_mode": { "enum": ["build", "yolo"] },
81
+ "model": { "type": "string", "minLength": 1, "maxLength": 512, "pattern": "^[^:/\\s]+$" },
82
+ "effort": { "enum": ["low", "medium", "high", "max"] },
83
+ "write_manifest": { "maxItems": 0 }
84
+ } } },
78
85
  { "if": { "required": ["permission_mode"], "properties": { "permission_mode": { "const": "plan" } } },
79
86
  "then": { "properties": { "write_manifest": { "maxItems": 0 } } } }
80
87
  ],
@@ -95,7 +102,7 @@
95
102
  },
96
103
  "wait": {
97
104
  "type": "object",
98
- "description": "Wait returns early only for an actionable pending request (permission requests need allow/deny; user-input requests carry the full embedded question and need answer with non-empty content) or a terminal result; ordinary progress, message receipts, already-responded and unsupported requests never wake it. The pending_requests output projection is capped at 100 actionable records, while the wake decision scans the full pending set. activity carries the latest text tail, a 200-char verified reasoning tail, tool calls started in the last 60 seconds, and telemetry status.",
105
+ "description": "Wait returns early only for an actionable pending request (permission requests need allow/deny; user-input requests carry the full embedded question and need answer with non-empty content) or a terminal result; ordinary progress, message receipts, already-responded and unsupported requests never wake it. The pending_requests output projection is capped at 100 actionable records, while the wake decision scans the full pending set. activity carries the text tail incrementally: each wait returns only the text appended since the previous wait (an empty tail means nothing new), every byte is delivered by wait at most once, and latest_text_truncated flags undelivered bytes that rolled out of the bounded window (that response degrades to the whole window); a terminal response also strips bytes repeating the embedded result page verbatim. activity also carries a 200-char verified reasoning tail, tool calls started in the last 60 seconds, and telemetry status.",
99
106
  "required": ["agent_id"],
100
107
  "properties": {
101
108
  "agent_id": { "type": "integer", "minimum": 10000000, "maximum": 99999999 },
@@ -105,7 +112,7 @@
105
112
  "additionalProperties": false
106
113
  },
107
114
  "observe": {
108
- "description": "Read captured task observations for zcode, dsh or codex. zcode and dsh expose at most 200 Unicode characters of public reasoning; codex reasoning is null. Coverage reports capture gaps and unsupported history truthfully.",
115
+ "description": "Read captured task observations for zcode, dsh, codex or agy. zcode and dsh expose at most 200 Unicode characters of public reasoning; codex and agy reasoning is null. Coverage reports capture gaps and unsupported history truthfully.",
109
116
  "type": "object",
110
117
  "required": ["agent_id"],
111
118
  "properties": {
@@ -31,6 +31,12 @@
31
31
  "status": "HIDDEN",
32
32
  "reasoning": null,
33
33
  "collected": false
34
+ },
35
+ "agy": {
36
+ "public": false,
37
+ "status": "HIDDEN",
38
+ "reasoning": null,
39
+ "collected": false
34
40
  }
35
41
  }
36
42
  }