@mono-agent/agent-app 0.4.0 → 0.4.1

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.
Files changed (173) hide show
  1. package/README.md +15 -5
  2. package/dist/adapter-send-tools-main.js +2 -2
  3. package/dist/adapter-send-tools-main.js.map +1 -1
  4. package/dist/adapter-send-tools.d.ts +72 -6
  5. package/dist/adapter-send-tools.d.ts.map +1 -1
  6. package/dist/adapter-send-tools.js +413 -38
  7. package/dist/adapter-send-tools.js.map +1 -1
  8. package/dist/app-config.d.ts +48 -11
  9. package/dist/app-config.d.ts.map +1 -1
  10. package/dist/app-config.js +98 -24
  11. package/dist/app-config.js.map +1 -1
  12. package/dist/app.d.ts +10 -0
  13. package/dist/app.d.ts.map +1 -1
  14. package/dist/app.js +659 -48
  15. package/dist/app.js.map +1 -1
  16. package/dist/artifact-retention.d.ts +32 -0
  17. package/dist/artifact-retention.d.ts.map +1 -0
  18. package/dist/artifact-retention.js +111 -0
  19. package/dist/artifact-retention.js.map +1 -0
  20. package/dist/audit-runs.d.ts +12 -0
  21. package/dist/audit-runs.d.ts.map +1 -0
  22. package/dist/audit-runs.js +68 -0
  23. package/dist/audit-runs.js.map +1 -0
  24. package/dist/backfill.d.ts +3 -7
  25. package/dist/backfill.d.ts.map +1 -1
  26. package/dist/backfill.js +115 -11
  27. package/dist/backfill.js.map +1 -1
  28. package/dist/background.d.ts +8 -1
  29. package/dist/background.d.ts.map +1 -1
  30. package/dist/background.js +202 -4
  31. package/dist/background.js.map +1 -1
  32. package/dist/broadcast-recorder.d.ts +27 -0
  33. package/dist/broadcast-recorder.d.ts.map +1 -0
  34. package/dist/broadcast-recorder.js +82 -0
  35. package/dist/broadcast-recorder.js.map +1 -0
  36. package/dist/channel-config-view.d.ts +28 -0
  37. package/dist/channel-config-view.d.ts.map +1 -0
  38. package/dist/channel-config-view.js +79 -0
  39. package/dist/channel-config-view.js.map +1 -0
  40. package/dist/channel-gate.d.ts +22 -0
  41. package/dist/channel-gate.d.ts.map +1 -0
  42. package/dist/channel-gate.js +35 -0
  43. package/dist/channel-gate.js.map +1 -0
  44. package/dist/channel-plugins.d.ts +39 -0
  45. package/dist/channel-plugins.d.ts.map +1 -0
  46. package/dist/channel-plugins.js +346 -0
  47. package/dist/channel-plugins.js.map +1 -0
  48. package/dist/channels.d.ts +62 -73
  49. package/dist/channels.d.ts.map +1 -1
  50. package/dist/channels.js +833 -126
  51. package/dist/channels.js.map +1 -1
  52. package/dist/cli.d.ts +53 -3
  53. package/dist/cli.d.ts.map +1 -1
  54. package/dist/cli.js +696 -28
  55. package/dist/cli.js.map +1 -1
  56. package/dist/config-reference.d.ts +24 -0
  57. package/dist/config-reference.d.ts.map +1 -0
  58. package/dist/config-reference.js +580 -0
  59. package/dist/config-reference.js.map +1 -0
  60. package/dist/configured-agent.d.ts +104 -0
  61. package/dist/configured-agent.d.ts.map +1 -0
  62. package/dist/configured-agent.js +578 -0
  63. package/dist/configured-agent.js.map +1 -0
  64. package/dist/consumer-contract.d.ts +36 -0
  65. package/dist/consumer-contract.d.ts.map +1 -0
  66. package/dist/consumer-contract.js +290 -0
  67. package/dist/consumer-contract.js.map +1 -0
  68. package/dist/doctor.d.ts +9 -0
  69. package/dist/doctor.d.ts.map +1 -1
  70. package/dist/doctor.js +252 -55
  71. package/dist/doctor.js.map +1 -1
  72. package/dist/index.d.ts +9 -3
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +5 -2
  75. package/dist/index.js.map +1 -1
  76. package/dist/init.d.ts +23 -7
  77. package/dist/init.d.ts.map +1 -1
  78. package/dist/init.js +91 -26
  79. package/dist/init.js.map +1 -1
  80. package/dist/install-skill.d.ts +1 -1
  81. package/dist/install-skill.js +2 -2
  82. package/dist/install-skill.js.map +1 -1
  83. package/dist/interaction-bridge.d.ts +72 -0
  84. package/dist/interaction-bridge.d.ts.map +1 -0
  85. package/dist/interaction-bridge.js +354 -0
  86. package/dist/interaction-bridge.js.map +1 -0
  87. package/dist/memory-command.d.ts +10 -0
  88. package/dist/memory-command.d.ts.map +1 -0
  89. package/dist/memory-command.js +649 -0
  90. package/dist/memory-command.js.map +1 -0
  91. package/dist/memory-recall-main.js +1 -1
  92. package/dist/memory-recall-main.js.map +1 -1
  93. package/dist/memory-recall.d.ts +41 -5
  94. package/dist/memory-recall.d.ts.map +1 -1
  95. package/dist/memory-recall.js +75 -5
  96. package/dist/memory-recall.js.map +1 -1
  97. package/dist/memory-rituals.d.ts +8 -11
  98. package/dist/memory-rituals.d.ts.map +1 -1
  99. package/dist/memory-rituals.js +26 -25
  100. package/dist/memory-rituals.js.map +1 -1
  101. package/dist/metrics.d.ts +13 -0
  102. package/dist/metrics.d.ts.map +1 -0
  103. package/dist/metrics.js +105 -0
  104. package/dist/metrics.js.map +1 -0
  105. package/dist/notify-destinations.d.ts +23 -0
  106. package/dist/notify-destinations.d.ts.map +1 -0
  107. package/dist/notify-destinations.js +79 -0
  108. package/dist/notify-destinations.js.map +1 -0
  109. package/dist/posted-message-index.d.ts +61 -0
  110. package/dist/posted-message-index.d.ts.map +1 -0
  111. package/dist/posted-message-index.js +178 -0
  112. package/dist/posted-message-index.js.map +1 -0
  113. package/dist/proactive-notify.d.ts +32 -0
  114. package/dist/proactive-notify.d.ts.map +1 -0
  115. package/dist/proactive-notify.js +62 -0
  116. package/dist/proactive-notify.js.map +1 -0
  117. package/dist/recipes/base.d.ts +15 -0
  118. package/dist/recipes/base.d.ts.map +1 -0
  119. package/dist/recipes/base.js +51 -0
  120. package/dist/recipes/base.js.map +1 -0
  121. package/dist/recipes/catalog.d.ts +4 -0
  122. package/dist/recipes/catalog.d.ts.map +1 -0
  123. package/dist/recipes/catalog.js +509 -0
  124. package/dist/recipes/catalog.js.map +1 -0
  125. package/dist/recipes/index.d.ts +11 -0
  126. package/dist/recipes/index.d.ts.map +1 -0
  127. package/dist/recipes/index.js +14 -0
  128. package/dist/recipes/index.js.map +1 -0
  129. package/dist/recipes/types.d.ts +70 -0
  130. package/dist/recipes/types.d.ts.map +1 -0
  131. package/dist/recipes/types.js +15 -0
  132. package/dist/recipes/types.js.map +1 -0
  133. package/dist/request-model-override.d.ts +67 -0
  134. package/dist/request-model-override.d.ts.map +1 -0
  135. package/dist/request-model-override.js +96 -0
  136. package/dist/request-model-override.js.map +1 -0
  137. package/dist/runs-health.d.ts +22 -0
  138. package/dist/runs-health.d.ts.map +1 -0
  139. package/dist/runs-health.js +144 -0
  140. package/dist/runs-health.js.map +1 -0
  141. package/dist/seen-conversations.d.ts +22 -0
  142. package/dist/seen-conversations.d.ts.map +1 -0
  143. package/dist/seen-conversations.js +120 -0
  144. package/dist/seen-conversations.js.map +1 -0
  145. package/dist/setup.d.ts +29 -0
  146. package/dist/setup.d.ts.map +1 -0
  147. package/dist/setup.js +97 -0
  148. package/dist/setup.js.map +1 -0
  149. package/dist/trigger-overrides.d.ts +17 -0
  150. package/dist/trigger-overrides.d.ts.map +1 -0
  151. package/dist/trigger-overrides.js +30 -0
  152. package/dist/trigger-overrides.js.map +1 -0
  153. package/dist/tui-command.d.ts +56 -0
  154. package/dist/tui-command.d.ts.map +1 -0
  155. package/dist/tui-command.js +160 -0
  156. package/dist/tui-command.js.map +1 -0
  157. package/dist/ui.d.ts.map +1 -1
  158. package/dist/ui.js +4 -0
  159. package/dist/ui.js.map +1 -1
  160. package/dist/web-command.d.ts +39 -0
  161. package/dist/web-command.d.ts.map +1 -0
  162. package/dist/web-command.js +151 -0
  163. package/dist/web-command.js.map +1 -0
  164. package/package.json +17 -17
  165. package/schema/mono-agent.config.schema.json +1686 -0
  166. package/skills/mono-agent-composer/SKILL.md +34 -9
  167. package/skills/mono-agent-composer/agents/openai.yaml +4 -0
  168. package/skills/mono-agent-composer/references/config-blueprint.md +52 -18
  169. package/skills/mono-agent-composer/references/discovery-questions.md +14 -16
  170. package/skills/mono-agent-composer/references/feature-coverage.md +19 -15
  171. package/skills/mono-agent-composer/references/package-map.md +17 -19
  172. package/skills/mono-agent-composer/references/playbooks.md +209 -0
  173. package/skills/mono-agent-composer/references/validation.md +9 -1
@@ -0,0 +1,209 @@
1
+ # Playbooks
2
+
3
+ Condensed, offline copy of the end-to-end recipes. Each maps a persona/goal to a
4
+ concrete `mono-agent.config.json` shape and the `init → configure → validate →
5
+ start → smoke` flow. Mirrors the published Playbooks index
6
+ (<https://mono-agent-docs.vercel.app/playbooks/>); this file is the
7
+ self-contained in-skill version so the composer can offer a matching recipe
8
+ without fetching anything. Before hand-assembling a config in the Composition
9
+ Flow, check whether one of these fits and adapt it. Verify every key against
10
+ `references/config-blueprint.md`.
11
+
12
+ ---
13
+
14
+ ## 1. Personal Telegram assistant with BuJo memory
15
+ **For:** an individual wanting a private assistant that remembers.
16
+ **Goal:** a Telegram bot (long polling) that captures every turn into BuJo memory with scheduled consolidation and recalls past notes semantically.
17
+ **Features:** `telegram.long-polling`, `channel.final-only-delivery`, `memory.bujo`, `memory.per-turn-capture`, `memory.bujo-consolidation`, `memory.recall-tool`, `memory.embeddings`.
18
+
19
+ ```json
20
+ {
21
+ "runtime": { "model": "claude:claude-sonnet-4-6" },
22
+ "telegram": { "enabled": true, "botToken": "...", "allowedChatIds": ["123456789"] },
23
+ "memory": {
24
+ "mode": "bujo", "path": "./.mono-agent/memory", "writeMode": "capture",
25
+ "embeddings": { "provider": "ollama", "model": "nomic-embed-text:v1.5", "endpoint": "http://localhost:11434", "dim": 768 },
26
+ "llm": { "provider": "ollama", "model": "qwen3.6:latest" },
27
+ "consolidation": { "enabled": true, "cron": "0 */2 * * *" }
28
+ }
29
+ }
30
+ ```
31
+ **Steps:** `ollama pull nomic-embed-text:v1.5 && ollama pull qwen3.6:latest` → `mono-agent init --model claude:claude-sonnet-4-6 --memory bujo` → add telegram + fill embeddings/llm + `writeMode: capture` → `mono-agent validate` (confirm memory liveness + consolidation cadence) → `mono-agent start`.
32
+ **Smoke:** send a fact from the allowed chat, then ask a paraphrased question later; confirm `memory_recall` in the run JSONL and that the answer uses it.
33
+
34
+ ## 2. Slack team bot with MCP tools
35
+ **For:** a DevOps engineer running a shared team bot.
36
+ **Goal:** a mention-triggered Slack Socket Mode bot with a custom MCP tool, Read/Grep, and `slack_send_message` for proactive posts.
37
+ **Features:** `slack.socket-mode`, `tool-policy.allowlist`, `tool-policy.mcp-servers`, `agent-app.adapter-send-tools`, `runtime.concurrency`.
38
+
39
+ ```json
40
+ {
41
+ "runtime": { "model": "claude:claude-sonnet-4-6" },
42
+ "slack": { "enabled": true, "botToken": "xoxb-...", "appToken": "xapp-...", "allowedChannelIds": ["C012345"], "botUserIds": ["U012345"], "mentionTextAliases": ["@agent"] },
43
+ "tools": { "allowedTools": ["Read", "Grep", "slack_send_message", "deployTool"], "mcpConfigPath": "./mcp.json" },
44
+ "concurrency": { "maxConcurrentRuns": 4, "maxPendingRuns": 8 }
45
+ }
46
+ ```
47
+ **Steps:** create a Slack app (Socket Mode app token + bot token) → `mono-agent init` → write `mcp.json` and add the MCP tool's exact name to `allowedTools` → add slack + `slack_send_message` → `validate` → `start`.
48
+ **Smoke:** mention the bot in an allowed channel; confirm the 👀 reaction, final answer, the MCP tool firing in the artifact, and that `slack_send_message` posts only to allowed channels.
49
+
50
+ ## 3. Fully local Ollama agent (no cloud)
51
+ **For:** a privacy-focused user with no cloud budget.
52
+ **Goal:** runs entirely on local Ollama via the Pi SDK, journal memory with local embeddings, no outbound network.
53
+ **Features:** `runtime.local-providers`, `runtime.multi-backend`, `memory.journal`, `memory.embeddings`, `sandbox.network-policy`.
54
+
55
+ ```json
56
+ {
57
+ "runtime": { "model": "pi:ollama:gemma4:31b" },
58
+ "providers": { "local": [{ "id": "ollama", "type": "ollama", "baseUrl": "http://localhost:11434", "enabled": true, "models": [{ "name": "gemma4:31b", "capabilities": { "context_window": 32768 } }] }] },
59
+ "memory": { "mode": "journal", "path": "./.mono-agent/memory", "embeddings": { "provider": "ollama", "model": "nomic-embed-text:v1.5", "endpoint": "http://localhost:11434", "dim": 768 } },
60
+ "sandbox": { "mode": "native", "network": { "mode": "localhost" } }
61
+ }
62
+ ```
63
+ **Steps:** pull both models → `mono-agent init --model pi:ollama:gemma4:31b --memory journal` → add `providers.local` + embeddings + `sandbox.network.mode: localhost` → `validate` (Ollama reachable, models pulled) → `start`.
64
+ **Smoke:** `curl -X POST` the webhook path; confirm a local-model response and no outbound non-localhost network in the artifact.
65
+
66
+ ## 4. OpenAI-compatible endpoint for Open WebUI
67
+ **For:** an AI-infra engineer fronting the agent with a chat UI.
68
+ **Goal:** expose `/v1` (SSE) so Open WebUI can stream and keep multi-turn state.
69
+ **Features:** `openai-api.chat-completions`, `runtime.provider-sessions`.
70
+
71
+ ```json
72
+ {
73
+ "runtime": { "model": "claude:claude-sonnet-4-6", "session": { "mode": "continuous", "idleTimeoutMs": 1800000 } },
74
+ "openaiApi": { "enabled": true, "host": "0.0.0.0", "port": 4040, "basePath": "/v1", "allowNonLoopback": true, "modelId": "my-agent", "apiKey": "sk-secret" }
75
+ }
76
+ ```
77
+ **Steps:** `mono-agent init` → add `openaiApi` (set `allowNonLoopback`, `apiKey`, `modelId`) + continuous session → `validate` → `start` → in Open WebUI add an OpenAI connection at `http://host:4040/v1` with the bearer.
78
+ **Smoke:** `curl /v1/models` returns `my-agent`; two calls with the same `X-OpenWebUI-Chat-Id` resume the session and stream via SSE.
79
+
80
+ ## 5. Webhook automation (sync + async)
81
+ **For:** a backend developer wiring the agent into a pipeline.
82
+ **Goal:** fast sync calls + long-running async jobs (202 + status polling) across multiple named endpoints.
83
+ **Features:** `webhook.http-invoke` (sync/async modes, multiple endpoints, per-endpoint prompt).
84
+
85
+ ```json
86
+ {
87
+ "runtime": { "model": "claude:claude-sonnet-4-6" },
88
+ "webhook": {
89
+ "enabled": true, "host": "127.0.0.1", "port": 8080, "defaultMode": "sync",
90
+ "endpoints": [
91
+ { "name": "invoke", "path": "/webhook/invoke", "mode": "sync", "prompt": "Respond to this request:" },
92
+ { "name": "jobs", "path": "/webhook/jobs", "mode": "async" }
93
+ ],
94
+ "retentionMs": 300000, "maxStoredRequests": 100
95
+ }
96
+ }
97
+ ```
98
+ **Steps:** `mono-agent init` (webhook already enabled) → add `endpoints[]` (or `webhook/*.md` files; unique names AND paths) → `validate` → `start`.
99
+ **Smoke:** `POST /webhook/invoke` for an immediate body; `POST /webhook/jobs` → 202 + status URL → poll until the result returns.
100
+
101
+ ## 6. Cron digest with proactive Slack notify
102
+ **For:** a data analyst wanting a scheduled briefing pushed to the team.
103
+ **Goal:** a timezone-aware cron job that builds a daily digest with shared history and posts it to Slack.
104
+ **Features:** `cron.scheduled-prompts`, `agent-app.adapter-send-tools`, `slack.socket-mode`, `memory.journal`.
105
+
106
+ ```json
107
+ {
108
+ "runtime": { "model": "claude:claude-sonnet-4-6" },
109
+ "slack": { "enabled": true, "botToken": "xoxb-...", "appToken": "xapp-...", "allowedChannelIds": ["C012345"] },
110
+ "tools": { "allowedTools": ["slack_send_message", "WebSearch"] },
111
+ "cron": { "jobs": [{ "id": "morning-digest", "enabled": true, "expression": "0 9 * * *", "timezone": "America/New_York", "prompt": "Build the morning digest and post it to #team via slack_send_message.", "conversationId": "daily-digest" }] }
112
+ }
113
+ ```
114
+ **Steps:** `mono-agent init` → add slack + `slack_send_message` → add the cron job (or `cron/morning-digest.md`) with `conversationId` + IANA timezone → `validate` → `start`.
115
+ **Smoke:** trigger a one-off tick; confirm `slack_send_message` posts the digest to the allowed channel and `conversationId` shares context across ticks.
116
+
117
+ ## 7. A2A provider + consumer pair
118
+ **For:** a platform integrator connecting two agents over A2A.
119
+ **Goal:** publish agent A as an A2A provider (Agent Card, bearer); configure agent B to discover and call it.
120
+ **Features:** `a2a.provider`, `a2a.consumer`.
121
+
122
+ ```json
123
+ {
124
+ "a2a": {
125
+ "enabled": true,
126
+ "provider": { "host": "127.0.0.1", "port": 4201, "requireBearer": true, "bearerToken": "..." },
127
+ "agent": { "name": "Research Agent", "description": "Does research.", "version": "0.1.0" },
128
+ "skill": { "id": "research", "name": "Research", "description": "Web research", "tags": ["research"] },
129
+ "consumer": { "remoteAgentUrls": ["http://127.0.0.1:4201"], "defaultRemoteAgentUrl": "http://127.0.0.1:4201", "bearerToken": "...", "timeoutMs": 30000 }
130
+ }
131
+ }
132
+ ```
133
+ **Steps:** provider — `init`, add `a2a.provider/agent/skill` + bearer, `validate`, `start`, confirm the Agent Card is reachable. Consumer — set `a2a.consumer` (or compose `createA2AConsumerResponder`), send text to the provider's Agent Card URL with the bearer.
134
+ **Smoke:** send a message to the provider's Agent Card URL with the bearer; confirm a real response.
135
+
136
+ ## 8. Multi-agent orchestration (`ask_collaborator`) — code
137
+ **For:** a workflow designer composing specialist agents.
138
+ **Goal:** one orchestrator delegates to named collaborator responders via the loopback `ask_collaborator` MCP tool.
139
+ **Features:** `orchestrator.ask-collaborator`, `harness.request-runtime-options`, `runtime.custom`.
140
+
141
+ ```ts
142
+ const ext = createCollaboratorToolRuntimeExtension({
143
+ collaborators: [
144
+ { id: "researcher", label: "Research", responder: researcher },
145
+ { id: "writer", label: "Writer", responder: writer },
146
+ ],
147
+ conversationId, maxCalls: 10,
148
+ });
149
+ // pass ext.runtimeOptions via createConfiguredAgentResponder({ runtimeOptionsForRequest })
150
+ // call ext.cleanup() on disposal to close the ephemeral MCP server
151
+ ```
152
+ **Smoke:** give a compound task ("research X then write a summary"); confirm the artifact shows `ask_collaborator` delegating to both, and `cleanup()` closes the MCP port.
153
+
154
+ ## 9. Sandboxed code agent (loopback only, deny .env)
155
+ **For:** a security team deploying an internal code assistant.
156
+ **Goal:** read repos + run Bash inside the native srt sandbox with loopback-only network access and protected secrets.
157
+ **Features:** `sandbox.mode`, `sandbox.network-policy`, `sandbox.filesystem-scopes`, `sandbox.fallback`, `tool-policy.allowlist`, `memory.journal`.
158
+
159
+ ```json
160
+ {
161
+ "runtime": { "model": "claude:claude-sonnet-4-6" },
162
+ "tools": { "allowedTools": ["Read", "Write", "Edit", "Glob", "Grep", "Bash"] },
163
+ "sandbox": { "mode": "native", "network": { "mode": "localhost" }, "readableRoots": ["."], "writableRoots": ["."], "denyWrite": [".env", ".env.*", ".git/config", ".git/hooks/**"], "fallback": "fail-closed" }
164
+ }
165
+ ```
166
+ **Steps:** `mono-agent init --memory journal` → allow Read/Write/Edit/Glob/Grep/Bash → `sandbox.mode native` + `network localhost` + deny-write defaults → keep `fallback: fail-closed` (do NOT set `unsafe-host-process`) → `validate` → `start`.
167
+ **Smoke:** ask it to read a file + run Bash (works), then fetch an external URL or write `.env` (both blocked in the artifact). Note: provider CLI bridges run their own tool loops and may not be srt-wrapped — pair with provider sandboxing.
168
+
169
+ ## 10. Phoenix-observed agent with the TUI
170
+ **For:** an agent builder evaluating runs in a tracing dashboard.
171
+ **Goal:** run locally with the TUI and stream every run to Phoenix as OpenInference spans; local JSONL is the fallback.
172
+ **Features:** `observability.phoenix-exporter`, `observability.jsonl-artifacts`, `observability.trace-registry`, `tui.chat`.
173
+
174
+ ```json
175
+ {
176
+ "runtime": { "model": "claude:claude-sonnet-4-6" },
177
+ "artifacts": { "dir": ".mono-agent/artifacts" },
178
+ "traceability": { "registryDir": ".mono-agent/trace-sources", "sourceId": "my-agent", "heartbeatMs": 10000 },
179
+ "observability": { "exporters": [{ "type": "phoenix", "endpoint": "http://127.0.0.1:6006/v1/traces", "projectName": "my-project", "includeSensitiveData": false, "timeoutMs": 5000 }] }
180
+ }
181
+ ```
182
+ **Steps:** start Phoenix (6006) → `init` → add artifacts/traceability/exporter → `validate` (POSTs an empty protobuf) → `start` (prints the Phoenix endpoint) → `mono-agent tui`.
183
+ **Smoke:** complete a TUI prompt; confirm a redacted JSONL artifact AND a Phoenix trace with merged tool spans under the project.
184
+
185
+ ## 11. Backfill historical runs to Phoenix
186
+ **For:** an ops engineer onboarding observability after the fact.
187
+ **Goal:** retroactively export recorded JSONL runs to Phoenix with original timestamps, idempotently.
188
+ **Features:** `observability.backfill`, `observability.phoenix-exporter`, `observability.jsonl-artifacts`.
189
+
190
+ ```json
191
+ { "artifacts": { "dir": ".mono-agent/artifacts" }, "observability": { "exporters": [{ "type": "phoenix", "endpoint": "http://127.0.0.1:6006/v1/traces", "projectName": "my-project" }] } }
192
+ ```
193
+ **Steps:** ensure `run-*.summary.json` + `run-*.events.jsonl` exist and Phoenix is reachable → `mono-agent backfill --all --since <iso> --until <iso> --dry-run` → `mono-agent backfill --all --since <iso>`.
194
+ **Smoke:** dry-run then real export; historical timestamps preserved in Phoenix and a second run does not duplicate spans (deterministic ids).
195
+
196
+
197
+ ## 12. Multi-model fallback chain with transcript resume
198
+ **For:** a reliability-minded builder who can't afford a single-provider outage.
199
+ **Goal:** a primary model with ordered backups the native failover router tries on retryable failures, resuming from the transcript tail — reported, never silent.
200
+ **Features:** `runtime.multi-backend`, `runtime.fallback-models`, `runtime.pi-native-tuning`, `runtime.provider-sessions`.
201
+
202
+ ```json
203
+ {
204
+ "runtime": { "model": "claude:claude-sonnet-4-6", "fallbackModels": ["pi:openai-codex:gpt-5.5", "pi:ollama:gemma4:31b"], "session": { "mode": "continuous" } },
205
+ "providers": { "local": [{ "id": "ollama", "type": "ollama", "baseUrl": "http://localhost:11434", "enabled": true }], "piNative": { "piMaxRetries": 2, "maxRetryDelayMs": 60000, "piSessionsRoot": ".mono-agent/sessions" } }
206
+ }
207
+ ```
208
+ **Steps:** `ollama pull gemma4:31b` → `mono-agent init --model claude:claude-sonnet-4-6 --fallback-models pi:openai-codex:gpt-5.5,pi:ollama:gemma4:31b` → add `providers.local` + `piNative.piSessionsRoot` → `validate` → `start`.
209
+ **Smoke:** force a retryable primary failure; confirm the run result reports failover to the next model (not silent) and the conversation resumes from the transcript tail.
@@ -12,6 +12,14 @@ mono-agent validate
12
12
 
13
13
  The report covers core config, runtime support for the primary and every fallback model, identity/skills/memory/MCP paths, the sandbox policy, the observability section (artifacts, traceability, and any configured exporters), and every channel (`ok` / `waiting` / `off` / `error`). Exit 0 means the folder is ready to start. Fix every `[error]`; `[waiting]` channels are simply unconfigured.
14
14
 
15
+ From a separate orchestration folder, validate a downstream consumer without changing cwd:
16
+
17
+ ```bash
18
+ mono-agent validate --consumer <agent-folder>
19
+ ```
20
+
21
+ The consumer folder's `.env` loads by default, relative `--config` and `--env-file` paths resolve inside that folder, and missing memory roots warn read-only instead of being created.
22
+
15
23
  Then start and confirm the status lines:
16
24
 
17
25
  ```bash
@@ -27,7 +35,7 @@ agent's configured skills root, e.g. `./skills`):
27
35
 
28
36
  ```bash
29
37
  node --input-type=module - <<'EOF'
30
- import { loadSkillIndexFromDirectory } from '@mono-agent/context';
38
+ import { loadSkillIndexFromDirectory } from '@mono-agent/agent-harness';
31
39
 
32
40
  const skills = await loadSkillIndexFromDirectory('<skillsRoot>');
33
41
  console.log(JSON.stringify(skills, null, 2));