docs: add Agap agent platform design (A2A, per-model queues, agents)
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CodeQL Critical Quality / Select Critical Quality shards (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (core-auth-secrets) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (config-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (gateway-runtime-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (channel-runtime-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (network-runtime-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (agent-runtime-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (mcp-process-runtime-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (memory-runtime-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (session-diagnostics-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (plugin-sdk-reply-runtime) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (provider-runtime-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (ui-control-plane) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (web-media-runtime-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (plugin-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (plugin-sdk-package-contract) (push) Has been cancelled
CodeQL Android Critical Security / Critical Security (android) (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CodeQL Critical Quality / Select Critical Quality shards (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (core-auth-secrets) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (config-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (gateway-runtime-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (channel-runtime-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (network-runtime-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (agent-runtime-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (mcp-process-runtime-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (memory-runtime-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (session-diagnostics-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (plugin-sdk-reply-runtime) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (provider-runtime-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (ui-control-plane) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (web-media-runtime-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (plugin-boundary) (push) Has been cancelled
CodeQL Critical Quality / Critical Quality (plugin-sdk-package-contract) (push) Has been cancelled
CodeQL Android Critical Security / Critical Security (android) (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Overall design for moving from a single tool-heavy Adolf to a multi-agent platform: agents as personas (prompt+memory+tools) that can swap backbones, models as the scarce queued resource (per-model queues with always-on / quota-gated / cost-gated / on-demand lifecycles), and A2A patterns (agent cards, task lifecycle, context-by-reference) to move work between them. Covers the required cases: Hindsight reflect as an async queued task to the large model, the Claude Code loop as just another queue-consuming agent, why queues are keyed by model rather than agent, and how the lab grows to remote llama / extra GPUs / research agents. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014t8Qg9gi7H7HtT8MncoXAB
This commit is contained in:
170
DESIGN-a2a-agents.md
Normal file
170
DESIGN-a2a-agents.md
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
# DESIGN — Agap Agent Platform (A2A, model queues, agents)
|
||||||
|
|
||||||
|
Status: **draft for review** · Owner: alvis · Drafted 2026-07-21
|
||||||
|
|
||||||
|
This is the overall design for turning the Agap homelab from "one Adolf carrying every
|
||||||
|
tool + a few background LLM calls" into a **multi-agent platform**: agents as
|
||||||
|
personas, models as queued compute, and A2A as the way work moves between them.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Why
|
||||||
|
|
||||||
|
Current pain, all observed on the live stack:
|
||||||
|
|
||||||
|
- **Duplicated LLM spend.** Every Adolf turn costs two Kimi calls: the reply
|
||||||
|
(~32.8K tokens in) and a *separate* background Hindsight retain/extraction
|
||||||
|
(~22.8K). Only ~425 tokens of that is the actual conversation.
|
||||||
|
- **Tool bloat.** One Adolf carries ~84 MCP tool schemas (~12K tokens) + ~26
|
||||||
|
built-in Kimi tools (~10K) on **every** turn, whether relevant or not.
|
||||||
|
- **Quota cliffs.** Kimi is a flat, window-limited subscription (~60 messages per
|
||||||
|
5h, ~300/week measured). When the window is spent, Adolf goes dark. There is no
|
||||||
|
graceful degradation and no way to park work until the window resets.
|
||||||
|
- **Background work is hardcoded to a model.** Hindsight's reflect/consolidate
|
||||||
|
call a fixed LLM directly. There is no scheduling, no priority, no quota
|
||||||
|
awareness, no way to say "do this on the big model when it's free".
|
||||||
|
- **No room to grow.** The ambition is autonomous research agents, remote llama
|
||||||
|
nodes, more GPUs, more agents. None of that fits a single hardcoded assistant.
|
||||||
|
|
||||||
|
## 2. Core concepts (and the distinctions that matter)
|
||||||
|
|
||||||
|
The central insight: **an agent is not a queue, and a model is not an agent.**
|
||||||
|
|
||||||
|
### Task
|
||||||
|
The unit of work. Durable, addressable, and **context-by-reference**: a task
|
||||||
|
carries *pointers* (memory bank id, git ref, board task id, file path), never
|
||||||
|
pasted context. Fields: id, intent, required capability/tier, target model queue,
|
||||||
|
priority, status, context refs, result ref, submitter, deadline.
|
||||||
|
|
||||||
|
### Model (backbone) — the scarce resource
|
||||||
|
A concrete LLM endpoint reached through the LiteLLM gateway. Examples today:
|
||||||
|
`kimi` (flat quota), `claude-haiku` (paid, already wired), local ollama
|
||||||
|
(`qwen3.5:4b`, `qwen3:8b`, `gemma3:4b`), later a remote llama box or a second GPU.
|
||||||
|
|
||||||
|
**Each model has its own queue and its own worker**, because the model is what is
|
||||||
|
actually scarce (quota, VRAM, cost, rate limit).
|
||||||
|
|
||||||
|
### Agent — the persona
|
||||||
|
An agent is a **combination of personality + system prompt + memory + tool scope**
|
||||||
|
(e.g. Adolf the proactive auditor; Torgash the marketplace analyst; a research
|
||||||
|
agent; the Claude coding loop). An agent is a *configuration*, not a runtime
|
||||||
|
resource. Critically:
|
||||||
|
|
||||||
|
> **An agent may change its backbone LLM.** Adolf on Kimi today, on a local model
|
||||||
|
> tomorrow, on Claude for a hard task. Therefore **queues are keyed by model, not
|
||||||
|
> by agent.** An agent *submits into* and *consumes from* model queues.
|
||||||
|
|
||||||
|
### Queue — per model, async, with a lifecycle
|
||||||
|
Queues are asynchronous by design and differ in how they drain:
|
||||||
|
|
||||||
|
| Lifecycle | Behaviour | Example |
|
||||||
|
|---|---|---|
|
||||||
|
| **always-on** | worker drains continuously in the background | local ollama models |
|
||||||
|
| **quota-gated** | drains until the window is exhausted, then parks and resumes on reset | Kimi |
|
||||||
|
| **cost-gated** | drains under a budget ceiling; stops/falls back when spent | paid Haiku/Flash |
|
||||||
|
| **on-demand** | node is woken/attached when work exists | future remote llama / extra GPU |
|
||||||
|
|
||||||
|
A task parked on a quota-gated queue is not lost — it waits for the window, or is
|
||||||
|
re-routed if it is urgent and another queue can satisfy the required capability.
|
||||||
|
|
||||||
|
## 3. Architecture
|
||||||
|
|
||||||
|
Four planes. Keeping them separate is the whole point.
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─ Coordination plane ──────────────────────────────────────────┐
|
||||||
|
│ Task registry + lifecycle (Kanboard as blackboard today) │
|
||||||
|
│ context-by-reference; claim/status; audit trail │
|
||||||
|
└───────────────────────────────────────────────────────────────┘
|
||||||
|
┌─ Agent plane ─────────────────────────────────────────────────┐
|
||||||
|
│ Agent registry: persona + system prompt + memory bank + │
|
||||||
|
│ tool scope + preferred capability tier │
|
||||||
|
│ (Adolf, Torgash, research-agent, claude-coder, …) │
|
||||||
|
└───────────────────────────────────────────────────────────────┘
|
||||||
|
┌─ Scheduling plane ────────────────────────────────────────────┐
|
||||||
|
│ Per-MODEL queues + workers; lifecycle policy (always-on / │
|
||||||
|
│ quota-gated / cost-gated / on-demand); priority; claiming │
|
||||||
|
└───────────────────────────────────────────────────────────────┘
|
||||||
|
┌─ Model plane ─────────────────────────────────────────────────┐
|
||||||
|
│ LiteLLM gateway: kimi | claude-haiku | local ollama | remote │
|
||||||
|
│ routing, fallback on 429/quota, per-agent virtual keys+budget │
|
||||||
|
└───────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**Shared context stores** (what task references point at): Hindsight (memory
|
||||||
|
banks), git/gitea (code + docs), Kanboard (task context), files.
|
||||||
|
|
||||||
|
### A2A on top
|
||||||
|
A2A gives the vocabulary we otherwise have to invent: **agent cards**
|
||||||
|
(capability advertisement), **task lifecycle states**, structured task
|
||||||
|
submission/tracking, and — most importantly — the **context-by-reference**
|
||||||
|
pattern (send a `contextId`, let the worker read the shared store). We adopt the
|
||||||
|
*patterns* first; the wire protocol can follow once more than one runtime needs
|
||||||
|
to interoperate.
|
||||||
|
|
||||||
|
## 4. Worked examples (the required minimal set)
|
||||||
|
|
||||||
|
**(1) Hindsight `reflect` becomes an A2A task.** Reflect is async by design.
|
||||||
|
Instead of Hindsight calling a fixed LLM inline, it **submits a task** — intent
|
||||||
|
`reflect`, context ref = bank + query, required tier = *large* — onto the
|
||||||
|
large-model queue. A worker runs it when that model has capacity/quota; the
|
||||||
|
result is written back to the bank. Same for consolidation. This removes the
|
||||||
|
hardcoded background call and makes memory work schedulable, priced, and
|
||||||
|
quota-aware. (See also the "in-loop extraction" option, which is the cheaper
|
||||||
|
counterpart for the *retain* path.)
|
||||||
|
|
||||||
|
**(2) The Claude Code CLI loop is just an agent.** `claude-coder` = an agent
|
||||||
|
whose persona is "implementer", whose backbone is a Claude model, and whose
|
||||||
|
consumption rule is *pull complex/coding tasks*. It is a **special case of a
|
||||||
|
queue consumer**, not a privileged component. This is why it already works:
|
||||||
|
Adolf files tasks, the Claude loop pulls them. We are formalising what exists.
|
||||||
|
|
||||||
|
**(3) Model queues ≠ agent queues.** Adolf may run on Kimi now and something else
|
||||||
|
later; Torgash may be cheap-tier normally and escalate to a large model for a
|
||||||
|
tricky comparison. So a task is queued against **the capability/model it needs**,
|
||||||
|
and the agent identity travels *with the task* (persona + memory refs), not with
|
||||||
|
the queue.
|
||||||
|
|
||||||
|
**(4) Queues drain differently.** The local queue works all night; the Kimi queue
|
||||||
|
stops at 100% of the 5h window and resumes after reset; a paid queue stops at its
|
||||||
|
budget. Submitters therefore must state urgency, and the router must be able to
|
||||||
|
re-route or park.
|
||||||
|
|
||||||
|
## 5. Growing the lab
|
||||||
|
|
||||||
|
- **More GPUs / remote llama** → new model entries + their own queues and
|
||||||
|
workers; `on-demand` lifecycle for nodes that are not always up. Nothing else
|
||||||
|
changes.
|
||||||
|
- **More agents** (research, finance, home) → new agent registry entries with
|
||||||
|
scoped tools + their own memory banks. They inherit queues and A2A for free.
|
||||||
|
- **Autonomous research agents** → long-running, low-priority tasks on always-on
|
||||||
|
local queues, escalating to the large model only for synthesis. This is exactly
|
||||||
|
what per-model queues + priorities make affordable.
|
||||||
|
|
||||||
|
## 6. Migration (phased, smallest useful step first)
|
||||||
|
|
||||||
|
1. **Registries + schemas** — model registry (endpoint, capability, lifecycle,
|
||||||
|
quota), agent registry (persona/prompt/memory/tools), task schema.
|
||||||
|
2. **One queue + one worker** — always-on local model, end-to-end.
|
||||||
|
3. **Quota-aware worker** — Kimi: park on exhaustion, resume on reset.
|
||||||
|
4. **A2A submission/tracking** with context-by-reference.
|
||||||
|
5. **Cut over the examples** — Hindsight reflect → queue; Claude loop → declared
|
||||||
|
agent/consumer; Adolf → declared agent with scoped tools.
|
||||||
|
6. **Scale** — remote/extra models, more agents.
|
||||||
|
|
||||||
|
## 7. Open questions
|
||||||
|
|
||||||
|
- Is Kanboard the queue itself, or does it stay the *human-facing* board while
|
||||||
|
workers use a dedicated queue store (and the two are synced)?
|
||||||
|
- Where does the routing decision live — submitter picks the tier, or a central
|
||||||
|
policy re-routes based on live quota/budget?
|
||||||
|
- How much A2A do we actually implement (patterns only vs the real protocol)?
|
||||||
|
- Claim/lease semantics: what happens to a task whose worker dies mid-run?
|
||||||
|
- Does an agent's memory bank follow it across backbones (yes, by design) — and
|
||||||
|
what does that mean for extraction quality when the backbone is weak?
|
||||||
|
|
||||||
|
## 8. Related
|
||||||
|
|
||||||
|
- Kanboard epic: architecture + LiteLLM gateway + multi-agent framework.
|
||||||
|
- Hindsight in-loop extraction (the cheap counterpart to queued reflect).
|
||||||
|
- Per-agent tool scoping (why Adolf stops carrying every tool).
|
||||||
Reference in New Issue
Block a user