docs: SSOT cleanup + changelog refresh (runtime-list drift, adapter counts, stale repo refs) #60

Merged
documentation-specialist merged 10 commits from docs/optimize-ssot-changelog into main 2026-06-02 05:41:45 +00:00
23 changed files with 505 additions and 16 deletions
+45
View File
@@ -0,0 +1,45 @@
import { source } from '@/lib/source';
export const dynamic = 'force-static';
// /llms.txt — the emerging convention (llmstxt.org) that lets answer engines
// (ChatGPT, Claude, Perplexity, Gemini) discover and cite the docs as a clean,
// link-first index. GEO: maximizes correct attribution of Molecule AI in
// LLM answers. Generated from the fumadocs source tree at build time.
export async function GET() {
const pages = source.getPages();
const base = 'https://doc.moleculesai.app';
const lines: string[] = [
'# Molecule AI',
'',
'> Molecule AI is an open-source operating system for AI agent organizations. Describe an org as code (`org.yaml`); the control plane provisions each agent as an isolated workspace on its own machine, communicating peer-to-peer over the A2A protocol and governed by the org hierarchy. Runtimes (claude-code, langgraph, crewai, autogen, deepagents, openclaw, hermes, gemini-cli, google-adk, external) and model providers (Anthropic, OpenAI, Google Vertex/Gemini, OpenRouter) are pluggable. Self-hostable or hosted SaaS.',
'',
'Key concepts: the org chart is the access-control policy (hierarchy gates A2A, memory scope, and event fan-out); each workspace is hard-isolated on its own machine (no shared filesystem, env, or secrets — A2A is the only channel); hierarchical memory has LOCAL / TEAM / GLOBAL scopes; tools reach every runtime over MCP.',
'',
'## Documentation',
'',
];
// group by top-level section for a readable, link-first index
const groups = new Map<string, { title: string; url: string; desc?: string }[]>();
for (const p of pages) {
const seg = p.url.replace(/^\/docs\/?/, '').split('/')[0] || 'overview';
const key = seg.charAt(0).toUpperCase() + seg.slice(1);
const arr = groups.get(key) ?? [];
arr.push({ title: p.data.title ?? p.url, url: `${base}${p.url}`, desc: p.data.description });
groups.set(key, arr);
}
for (const [section, items] of groups) {
lines.push(`### ${section}`);
for (const it of items) {
lines.push(`- [${it.title}](${it.url})${it.desc ? `: ${it.desc}` : ''}`);
}
lines.push('');
}
return new Response(lines.join('\n'), {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
});
}
+12
View File
@@ -0,0 +1,12 @@
import type { MetadataRoute } from 'next';
// robots.txt — allow all crawlers (including AI answer-engine bots:
// GPTBot, ClaudeBot, PerplexityBot, Google-Extended) and point them at
// the sitemap. We *want* docs cited by LLMs (GEO), so nothing is disallowed.
export default function robots(): MetadataRoute.Robots {
return {
rules: [{ userAgent: '*', allow: '/' }],
sitemap: 'https://doc.moleculesai.app/sitemap.xml',
host: 'https://doc.moleculesai.app',
};
}
+31
View File
@@ -0,0 +1,31 @@
import type { MetadataRoute } from 'next';
import { source } from '@/lib/source';
const BASE = 'https://doc.moleculesai.app';
// Static sitemap of every documentation page, generated from the fumadocs
// source tree at build time. Helps search engines and answer engines
// (Google, Bing, Perplexity, ChatGPT) discover and crawl the full docs set.
export default function sitemap(): MetadataRoute.Sitemap {
const now = new Date();
const docPages = source.getPages().map((page) => ({
url: `${BASE}${page.url}`,
lastModified: now,
changeFrequency: 'weekly' as const,
priority: page.url === '/docs' ? 1.0 : 0.7,
}));
const staticRoutes = [
{ url: `${BASE}/`, changeFrequency: 'weekly' as const, priority: 0.9 },
{ url: `${BASE}/docs`, changeFrequency: 'weekly' as const, priority: 1.0 },
].map((r) => ({ ...r, lastModified: now }));
// de-dupe /docs if it also appears in docPages
const seen = new Set<string>();
return [...staticRoutes, ...docPages].filter((e) => {
if (seen.has(e.url)) return false;
seen.add(e.url);
return true;
});
}
+1 -1
View File
@@ -12,7 +12,7 @@ Adapters live in `workspace/adapters/<runtime>/` and are auto-discovered at star
The runtime is selected via `config.yaml`:
```yaml
runtime: claude-code # or: langgraph, openclaw, deepagents, crewai, autogen
runtime: claude-code # or: langgraph, crewai, autogen, deepagents, openclaw, hermes, gemini-cli, google-adk, external
runtime_config:
model: sonnet
auth_token_file: .auth-token
+1 -1
View File
@@ -123,7 +123,7 @@ env:
| `description` | Yes | What this workspace does |
| `version` | Yes | Semantic version |
| `tier` | Yes | 1-4, determines deployment method |
| `runtime` | No | Adapter to use: `langgraph` (default), `claude-code`, `crewai`, `autogen`, `deepagents`, `openclaw`. See [Agent Runtime Adapters](./cli-runtime.md). |
| `runtime` | No | Adapter to use: `claude-code`, `langgraph` (default), `crewai`, `autogen`, `deepagents`, `openclaw`, `hermes`, `gemini-cli`, `google-adk`, or `external`. See [Agent Runtime Adapters](./cli-runtime.md). The canonical set is the control-plane provider registry. |
| `model` | Yes | LangChain-compatible provider string (e.g. `anthropic:claude-sonnet-4-6`). Overridden by `MODEL_PROVIDER` env var if set. |
| `prompt_files` | No | Ordered list of markdown files to load as system prompt. Defaults to `["system-prompt.md"]` if omitted. `MEMORY.md` and `USER.md` are auto-appended when present so frozen memory snapshots do not need to be duplicated here. Supports any agent framework's file structure (OpenClaw, Claude Code, etc.) |
| `shared_context` | No | Files from this workspace's config dir to share with direct children. Children fetch these at startup and inject into their system prompt as `## Parent Context`. 1-level inheritance only (grandchildren don't see grandparent's context). |
+6
View File
@@ -5,6 +5,12 @@ title: "Skills"
A skill is a package that gives an agent knowledge, instructions, and optionally executable tools. Skills are the primary way to customize what a workspace agent can do.
<img
src="/diagrams/skills-loop.svg"
alt="Skills and the self-improvement loop: (1) capture — an agent writes a memory (a fact or how-to) during work; (2) signal — the same approach succeeds repeatedly across tasks; (3) promote — it is packaged as a Skill (SKILL.md plus optional tools) added to the workspace; (4) hot-reload — a file watcher injects it into the prompt live, with no restart — so the agent gets durably better over time. Skills come from three places: workspace-local skills/, plugin-mounted shared skills, and this promotion loop; all are hot-reloadable and visible to peers via the Agent Card."
style={{ width: '100%', height: 'auto', margin: '1rem 0' }}
/>
The skill package shape follows the same `SKILL.md`/frontmatter conventions used by [ClawHub](https://clawhub.ai/)-style skills, but this runtime keeps the lifecycle local: skills are installed, audited, published, and hot-reloaded inside a workspace rather than managed through a separate registry layer.
## Skill Package Structure
@@ -9,16 +9,20 @@ The `workspace/` directory is Molecule AI's unified runtime image. Every provisi
## Runtime Matrix In Current `main`
Current `main` ships six adapters:
Current `main` ships ten runtimes:
- `langgraph`
- `deepagents`
- `claude-code`
- `langgraph`
- `crewai`
- `autogen`
- `deepagents`
- `openclaw`
- `hermes`
- `gemini-cli`
- `google-adk`
- `external` (bring-your-own agent — no platform-managed container)
This is the merged runtime surface today. Branch-level experiments such as NemoClaw are separate and should be treated as roadmap/WIP, not merged support.
This is the merged runtime surface today; the canonical set is the control-plane provider registry. Branch-level experiments are separate and should be treated as roadmap/WIP, not merged support.
Adapter-specific behavior is documented in [Agent Runtime Adapters](./cli-runtime.md).
@@ -5,6 +5,12 @@ title: "Registry & Heartbeat"
Every workspace registers with the platform on startup and sends a heartbeat every 30 seconds. This is how the platform knows which workspaces are alive and where to find them.
<img
src="/diagrams/registry-heartbeat.svg"
alt="Registry and heartbeat sequence: a workspace agent POSTs /registry/register with its Agent Card; the platform writes the card to Postgres, sets ws:{id}=online in Redis with a 60s TTL, returns a one-time auth_token, and broadcasts WORKSPACE_ONLINE. Every 30s the agent heartbeats (error_rate, active_tasks, uptime), refreshing the TTL and evaluating a degraded threshold. If heartbeats stop, the Redis TTL expires and the keyspace event drives the platform to mark the workspace offline and broadcast WORKSPACE_OFFLINE — liveness is push-based and the platform never sits in the agent-to-agent data path."
style={{ width: '100%', height: 'auto', margin: '1rem 0' }}
/>
## Registration Flow
When a workspace container starts:
+6
View File
@@ -9,6 +9,12 @@ Molecule AI's memory model is built around one principle:
That is the purpose of **HMA: Hierarchical Memory Architecture**.
<img
src="/diagrams/memory-hma.svg"
alt="Hierarchical Memory Architecture: nested LOCAL (private to one agent), TEAM (shared with parent and siblings), and GLOBAL (org-wide, read by all, written from root only) scopes over the org tree, with four surfaces — agent_memories, workspace_memory KV, session recall, and the awareness namespace — in a durable per-workspace namespace workspace:<id>. Reach is enforced by the same CanCommunicate hierarchy used for A2A. A side loop shows memory → repeated success → skill promotion → hot-reload, the self-improvement flywheel."
style={{ width: '100%', height: 'auto', margin: '1rem 0' }}
/>
## The Three Scopes
| Scope | Meaning | Intended use |
@@ -54,7 +54,7 @@ Molecule AI is an **org-native control plane for heterogeneous AI agent teams**.
- **Canvas-based visual team building** with drag-to-nest hierarchy
- **Comprehensive control plane operations** — registry, heartbeats, lifecycle, approvals, secrets, traces, bundles
Six runtime adapters ship production-ready on `main`: LangGraph, DeepAgents, Claude Code, CrewAI, AutoGen, OpenClaw.
Ten runtime adapters ship production-ready on `main`: Claude Code, LangGraph, CrewAI, AutoGen, DeepAgents, OpenClaw, Hermes, Gemini CLI, Google ADK, plus `external` (bring-your-own agent). The canonical set is the control-plane provider registry.
---
@@ -70,7 +70,7 @@ Six runtime adapters ship production-ready on `main`: LangGraph, DeepAgents, Cla
|---|-----------|-------------|
| 1 | **Workspace = role, not task** | Internal AI model can swap, but organizational identity persists across model/framework changes |
| 2 | **Org chart = topology** | Hierarchy determines communication boundaries — no manual edge wiring needed |
| 3 | **Heterogeneous runtime support** | 6 adapters shipped; teams choose freely without forced standardization |
| 3 | **Heterogeneous runtime support** | 10 runtimes shipped; teams choose freely without forced standardization |
| 4 | **Memory follows org boundaries** | HMA prevents over-sharing, aligns data isolation with organizational structure |
| 5 | **Skill evolution loop** | memory → signal → skill → hot-reload → operational improvement (self-improving flywheel) |
@@ -107,8 +107,9 @@ Six runtime adapters ship production-ready on `main`: LangGraph, DeepAgents, Cla
┌─────────────────────────────────────────────────────────────┐
│ Workspace Runtime (Python 3.11+ Docker image) │
│ Pluggable adapters: LangGraph, DeepAgents, Claude Code,
CrewAI, AutoGen, OpenClaw
│ Pluggable adapters: claude-code, langgraph, crewai,
autogen, deepagents, openclaw, hermes, gemini-cli,
│ google-adk, external │
│ A2A protocol server · heartbeat · skills · HMA memory │
└─────────────────────────────────────────────────────────────┘
@@ -156,7 +157,7 @@ Six runtime adapters ship production-ready on `main`: LangGraph, DeepAgents, Cla
**3. Workspace Runtime (Python 3.11+)**
- Unified `workspace/` Docker image
- Adapter-driven execution (6 adapters)
- Adapter-driven execution (10 runtimes)
- A2A server via Uvicorn
- Heartbeat loop (30s default)
- Skill hot-reload system (~3 second propagation)
@@ -516,7 +517,7 @@ description: ""
version: "1.0.0"
tier: 2 # 1=sandboxed, 2=standard, 3=privileged, 4=full-host
model: "anthropic:claude-sonnet-4-6" # provider:model syntax
runtime: "langgraph" # langgraph | deepagents | claude-code | crewai | autogen | openclaw
runtime: "langgraph" # claude-code | langgraph | crewai | autogen | deepagents | openclaw | hermes | gemini-cli | google-adk | external
runtime_config: # Runtime-specific settings
command: "claude" # For CLI runtimes
args: []
@@ -1143,7 +1144,7 @@ Molecule AI's workspace abstraction is **runtime-agnostic by design**. A workspa
| Phase | Era | Systems | Status |
|-------|-----|---------|--------|
| **NOW** | Software Agent Teams | LLM agents in Docker, 6 adapters, HMA, Langfuse, A2A | **LIVE on main** |
| **NOW** | Software Agent Teams | LLM agents in Docker, 10 runtimes, HMA, Langfuse, A2A | **LIVE on main** |
| **NEXT** | Terminal + Device Agents | Terminal bots, browser agents, IoT controllers, CI/CD agents | **BUILDING** |
| **HORIZON** | Embodied Robot Teams | Warehouse robots, autonomous vehicles, manufacturing cells, field inspection | **HORIZON** |
+6
View File
@@ -5,6 +5,12 @@ title: "Provisioner"
The provisioner is the platform component that deploys workspace containers and VMs. It is triggered when a workspace is created, imported from a bundle, or expanded into a team.
<img
src="/diagrams/provisioning-lifecycle.svg"
alt="Workspace lifecycle states: create → provisioning (image pull, container, config) → starting (register, await heartbeat) → online (serving A2A) on the happy path, reaching online only after the first heartbeat. Failure paths are fail-loud: a runtime/config mismatch or a 3-minute timeout lands in failed (with last_sample_error) rather than silently booting a default. From online, high error rate → degraded and a missed TTL → offline, which auto-restarts and re-registers back to online; paused is an explicit operator action that resumes to provisioning."
style={{ width: '100%', height: 'auto', margin: '1rem 0' }}
/>
## How It Works
1. Platform receives a workspace creation request (API call or bundle import)
@@ -5,6 +5,12 @@ title: "Workspace Tiers"
Four tiers control the security boundary for each workspace. Higher tiers get more system access but less isolation.
<img
src="/diagrams/tiers.svg"
alt="Workspace tiers T1T4: T1 Sandboxed (core tools only — delegate, memory, peer messaging; most restricted, lowest budget); T2 Standard (adds browser and web access — the common default); T3 Privileged (adds computer-use and broader system access); T4 Full Access (adds full host access and the Docker socket — least sandboxed, for infra/ops agents, use sparingly). Every tier runs on its own isolated machine; tier controls in-machine capability and budget. Tools are gated: browser needs T2+, computer-use needs T3+."
style={{ width: '100%', height: 'auto', margin: '1rem 0' }}
/>
## Tier Overview
| Tier | Name | Container Flags | Use Case |
+18
View File
@@ -8,6 +8,24 @@ Entries are published daily at 23:50 UTC.
---
## 2026-06-01
### 🔒 Security
- **Hierarchy access-control hardened — root-sibling bypass removed**: `CanCommunicate` no longer treats all root-level workspaces as mutually reachable. Cross-team messaging between unrelated root workspaces is now denied unless an explicit parent/child or shared-parent relationship exists, closing a lateral-reach gap in the A2A authorization model. (`molecule-core` [#1961](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1961))
### ✨ Improvements
- **Google ADK runtime on Vertex AI (keyless)**: the `google-adk` runtime now serves **Gemini 2.5 Pro on Vertex AI** using keyless Application Default Credentials over Workload Identity Federation — no API key on disk. Added as a first-class pluggable runtime alongside the existing nine. (provider registry sync, `molecule-core` [#2103](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/2103))
- **Provisioning fails loud on runtime/config mismatch**: if a workspace names a runtime whose template isn't available at provision time, provisioning now aborts with a clear failure instead of silently seeding a default config — so a misconfigured agent fails visibly rather than appearing online but answering generically.
- **`auth_token` returned on workspace creation**: `POST /workspaces` now includes the issued `auth_token` in its `201` response, so clients no longer need a second call to retrieve it. (`molecule-core` [#1669](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1669))
### 🧹 Internal
- Provider serving-URL fixes (Kimi-coding `/v1`, Gemini api-key base_url) mirrored from the control-plane SSOT; CI review-check now distinguishes token-provisioning (all-403) failures; stale `molecule-monorepo` references cleaned up across docs. (`molecule-core` [#2103](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/2103), [#1967](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1967), [#1951](https://git.moleculesai.app/molecule-ai/molecule-core/pulls/1951))
---
## 2026-05-18
_No customer-visible changes on 2026-05-18. All PRs merged were internal CI fixes, test fixture cleanups, or RFCs._
+8
View File
@@ -3,6 +3,14 @@ title: Concepts
description: The core primitives that compose every Molecule AI org — workspaces, plugins, channels, schedules, tokens, external agents, and the canvas.
---
<img
src="/diagrams/how-it-works-simple.svg"
alt="How Molecule AI works in 30 seconds, four steps: (1) you write one declarative org.yaml — roles, hierarchy, runtime, model, tools; (2) the control plane provisions one isolated machine per agent (open source, self-host or SaaS); (3) agents collaborate over the A2A protocol with the org hierarchy as the rules; (4) you watch and steer on a live Canvas — approve, chat, delegate. Runtimes and models are pluggable (Claude, Gemini on Vertex, GPT, and more), and any agent or device that speaks A2A can join."
style={{ width: '100%', height: 'auto', margin: '1rem 0' }}
/>
For the full picture — control plane, tenant isolation, governance, and how external agents join:
<img
src="/diagrams/concepts-overview.svg"
alt="Molecule AI core concepts: an org.yaml is imported by the Control Plane, which provisions a tenant of agent workspaces that communicate peer-to-peer over A2A — governed by the org hierarchy — while the Canvas streams live state and external agents join over HTTP."
+1 -1
View File
@@ -26,7 +26,7 @@ lands in the watch list with a colliding term, add a row here.
| **team** | A named cluster of workspaces under a PM (org template `expand_team`). Used for role grouping in Canvas. | **CrewAI**: a "crew" is a sequence of agents that pass a task through a declared order. Our "team" is an org-chart abstraction, not an execution order. |
| **skill** | A directory with `SKILL.md` that an agent invokes via the `Skill` tool. Skills are documentation + optional scripts that teach an agent a recipe. | **Anthropic Skills API**: nearly identical. **CrewAI tool**: closer to our plugin's MCP tool, not our skill. |
| **channel** | An outbound/inbound social integration (Telegram, Slack, …) per-workspace, wired in `workspace_channels`. | Slack's "channel": the container for messages. We use "channel" for the adapter + credentials, not the conversation itself. |
| **runtime** | The execution engine image tag for a workspace: one of `langgraph`, `claude-code`, `openclaw`, `crewai`, `autogen`, `deepagents`, `hermes`. | **LangGraph runtime**: the Python process running the graph. We use "runtime" for the Docker image + adapter pairing, not the inner process. |
| **runtime** | The execution engine image tag for a workspace, selected by the `runtime` field in `config.yaml`: `claude-code`, `langgraph`, `crewai`, `autogen`, `deepagents`, `openclaw`, `hermes`, `gemini-cli`, `google-adk`, plus `external` (no container — bring-your-own agent). New runtimes drop in behind one `BaseAdapter` contract; the canonical set lives in the control-plane provider registry, not here. | **LangGraph runtime**: the Python process running the graph. We use "runtime" for the Docker image + adapter pairing, not the inner process. |
## GitHub Awesome Copilot disambiguation
+1 -1
View File
@@ -67,7 +67,7 @@ When opencode connects to the Molecule MCP endpoint, the agent gains access to:
"tool": "delegate_task",
"arguments": {
"target": "research-lead",
"task": "Summarise the last 7 days of commits in Molecule-AI/molecule-monorepo"
"task": "Summarise the last 7 days of commits in molecule-ai/molecule-core"
}
}
```
+1 -1
View File
@@ -100,7 +100,7 @@ Once connected, opencode can call Molecule tools directly in its tool loop:
"tool": "delegate_task",
"arguments": {
"target": "research-lead",
"task": "Summarise the last 7 days of commits in Molecule-AI/molecule-monorepo"
"task": "Summarise the last 7 days of commits in molecule-ai/molecule-core"
}
}
```
+56
View File
@@ -0,0 +1,56 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1120 360" font-family="Inter, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif">
<defs>
<filter id="sh" x="-20%" y="-20%" width="140%" height="140%"><feDropShadow dx="0" dy="2" stdDeviation="5" flood-color="#0b1220" flood-opacity="0.12"/></filter>
<marker id="a" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#4f46e5"/></marker>
</defs>
<rect width="1120" height="360" fill="#fbfcfe"/>
<text x="48" y="50" font-size="23" font-weight="700" fill="#15181f">How Molecule AI works — in 30 seconds</text>
<text x="48" y="78" font-size="14" fill="#5b6472">Describe an org in one file. The platform runs it as a team of agents that talk to each other and show up live on a canvas.</text>
<!-- 1 org.yaml -->
<g filter="url(#sh)"><rect x="48" y="120" width="220" height="150" rx="14" fill="#fff7ed" stroke="#f59e0b" stroke-width="1.6"/></g>
<circle cx="74" cy="146" r="14" fill="#f59e0b"/><text x="74" y="151" font-size="15" font-weight="700" fill="#fff" text-anchor="middle">1</text>
<text x="98" y="151" font-size="15" font-weight="700" fill="#b45309">You write</text>
<text x="68" y="186" font-size="15" font-weight="700" fill="#15181f" font-family="monospace">org.yaml</text>
<text x="68" y="212" font-size="12.5" fill="#92560a">roles · hierarchy</text>
<text x="68" y="232" font-size="12.5" fill="#92560a">runtime · model · tools</text>
<text x="68" y="256" font-size="11.5" fill="#b45309">one declarative file</text>
<!-- 2 control plane -->
<g filter="url(#sh)"><rect x="316" y="120" width="220" height="150" rx="14" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.6"/></g>
<circle cx="342" cy="146" r="14" fill="#4f46e5"/><text x="342" y="151" font-size="15" font-weight="700" fill="#fff" text-anchor="middle">2</text>
<text x="366" y="151" font-size="15" font-weight="700" fill="#3730a3">Platform builds it</text>
<text x="336" y="188" font-size="14" font-weight="700" fill="#15181f">Control plane</text>
<text x="336" y="212" font-size="12.5" fill="#4338ca">provisions one isolated</text>
<text x="336" y="230" font-size="12.5" fill="#4338ca">machine per agent</text>
<text x="336" y="256" font-size="11.5" fill="#6366f1">open source · self-host or SaaS</text>
<!-- 3 agents A2A -->
<g filter="url(#sh)"><rect x="584" y="120" width="220" height="150" rx="14" fill="#ffffff" stroke="#10b981" stroke-width="1.6"/></g>
<circle cx="610" cy="146" r="14" fill="#10b981"/><text x="610" y="151" font-size="15" font-weight="700" fill="#fff" text-anchor="middle">3</text>
<text x="634" y="151" font-size="15" font-weight="700" fill="#047857">Agents collaborate</text>
<!-- mini org -->
<rect x="664" y="178" width="60" height="26" rx="7" fill="#0f172a"/><text x="694" y="195" font-size="10.5" font-weight="700" fill="#fff" text-anchor="middle">lead</text>
<rect x="606" y="226" width="56" height="24" rx="7" fill="#f8fafc" stroke="#5b5bd6"/><text x="634" y="242" font-size="10" fill="#15181f" text-anchor="middle">agent</text>
<rect x="726" y="226" width="56" height="24" rx="7" fill="#f8fafc" stroke="#5b5bd6"/><text x="754" y="242" font-size="10" fill="#15181f" text-anchor="middle">agent</text>
<path d="M694,204 L634,226" stroke="#94a3b8" stroke-width="1.2" fill="none"/>
<path d="M694,204 L754,226" stroke="#94a3b8" stroke-width="1.2" fill="none"/>
<path d="M662,238 L726,238" stroke="#10b981" stroke-width="2" fill="none"/>
<text x="694" y="265" font-size="11" fill="#047857" text-anchor="middle">talk over A2A · hierarchy = the rules</text>
<!-- 4 canvas -->
<g filter="url(#sh)"><rect x="852" y="120" width="220" height="150" rx="14" fill="#f6f4ff" stroke="#7c6df2" stroke-width="1.6"/></g>
<circle cx="878" cy="146" r="14" fill="#7c6df2"/><text x="878" y="151" font-size="15" font-weight="700" fill="#fff" text-anchor="middle">4</text>
<text x="902" y="151" font-size="15" font-weight="700" fill="#3b2fae">You watch &amp; steer</text>
<text x="872" y="188" font-size="14" font-weight="700" fill="#15181f">Canvas</text>
<text x="872" y="212" font-size="12.5" fill="#5b3fc4">live org chart, every</text>
<text x="872" y="230" font-size="12.5" fill="#5b3fc4">message &amp; task in real time</text>
<text x="872" y="256" font-size="11.5" fill="#7c6df2">approve · chat · delegate</text>
<!-- arrows -->
<path d="M268,195 L316,195" stroke="#4f46e5" stroke-width="2.2" fill="none" marker-end="url(#a)"/>
<path d="M536,195 L584,195" stroke="#4f46e5" stroke-width="2.2" fill="none" marker-end="url(#a)"/>
<path d="M804,195 L852,195" stroke="#4f46e5" stroke-width="2.2" fill="none" marker-end="url(#a)"/>
<text x="560" y="318" font-size="12.5" fill="#64748b" text-anchor="middle">Runtimes &amp; models are pluggable — Claude, Gemini (Vertex), GPT, and more — and any agent or device that speaks A2A can join.</text>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

+50
View File
@@ -0,0 +1,50 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1120 560" font-family="Inter, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif">
<defs>
<filter id="sh" x="-20%" y="-20%" width="140%" height="140%"><feDropShadow dx="0" dy="2" stdDeviation="4" flood-color="#0b1220" flood-opacity="0.10"/></filter>
<marker id="ag" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#b45309"/></marker>
</defs>
<rect width="1120" height="560" fill="#fbfcfe"/>
<text x="44" y="46" font-size="24" font-weight="700" fill="#15181f">Hierarchical Memory (HMA) — scoped by the org tree</text>
<text x="44" y="72" font-size="13.5" fill="#5b6472">Each agent has a durable private namespace. What it can read/write widens with scope; the same hierarchy that gates A2A gates memory.</text>
<!-- nested scopes -->
<g filter="url(#sh)"><rect x="44" y="100" width="640" height="360" rx="16" fill="#fffdf7" stroke="#f59e0b" stroke-width="1.6"/></g>
<text x="66" y="128" font-size="15" font-weight="700" fill="#b45309">GLOBAL</text>
<text x="150" y="128" font-size="12.5" fill="#92560a">org-wide knowledge · read by all · write from root only</text>
<rect x="76" y="146" width="576" height="280" rx="13" fill="#fff8ee" stroke="#f4c98a" stroke-width="1.4"/>
<text x="98" y="174" font-size="15" font-weight="700" fill="#b45309">TEAM</text>
<text x="170" y="174" font-size="12.5" fill="#92560a">shared with parent + siblings in the same subtree</text>
<rect x="108" y="192" width="512" height="216" rx="11" fill="#fffefb" stroke="#f4d3a4" stroke-width="1.3"/>
<text x="130" y="220" font-size="15" font-weight="700" fill="#b45309">LOCAL</text>
<text x="196" y="220" font-size="12.5" fill="#92560a">private working memory · this agent only</text>
<!-- surfaces inside local -->
<g font-size="12" fill="#15181f">
<rect x="130" y="240" width="220" height="36" rx="8" fill="#fff" stroke="#e7d3b4"/><text x="146" y="263">agent_memories <tspan fill="#94a3b8">(scoped facts)</tspan></text>
<rect x="362" y="240" width="236" height="36" rx="8" fill="#fff" stroke="#e7d3b4"/><text x="378" y="263">workspace_memory <tspan fill="#94a3b8">(KV / canvas)</tspan></text>
<rect x="130" y="286" width="220" height="36" rx="8" fill="#fff" stroke="#e7d3b4"/><text x="146" y="309">session recall <tspan fill="#94a3b8">(search)</tspan></text>
<rect x="362" y="286" width="236" height="36" rx="8" fill="#fff" stroke="#e7d3b4"/><text x="378" y="309">awareness namespace</text>
</g>
<text x="130" y="350" font-size="11.5" fill="#92560a">Durable per-workspace namespace: <tspan font-family="monospace" fill="#b45309">workspace:&lt;id&gt;</tspan> — survives restarts &amp; re-provision.</text>
<text x="130" y="372" font-size="11.5" fill="#92560a">Reach is enforced by the same <tspan font-family="monospace" fill="#b45309">CanCommunicate</tspan> hierarchy rule used for A2A and events.</text>
<!-- promotion loop -->
<g filter="url(#sh)"><rect x="712" y="100" width="364" height="360" rx="16" fill="#ecfdf5" stroke="#10b981" stroke-width="1.5"/></g>
<text x="734" y="128" font-size="14.5" font-weight="700" fill="#047857">Memory → Skill promotion loop</text>
<text x="734" y="150" font-size="11.5" fill="#0f766e">how an agent gets durably better over time</text>
<g font-size="12.5" fill="#065f46">
<rect x="734" y="168" width="320" height="44" rx="9" fill="#fff" stroke="#a7f3d0"/><text x="750" y="186" font-weight="600">1 · capture</text><text x="750" y="203" font-size="11" fill="#0f766e">agent writes a memory (a fact / how-to)</text>
<rect x="734" y="224" width="320" height="44" rx="9" fill="#fff" stroke="#a7f3d0"/><text x="750" y="242" font-weight="600">2 · signal</text><text x="750" y="259" font-size="11" fill="#0f766e">the same approach succeeds repeatedly</text>
<rect x="734" y="280" width="320" height="44" rx="9" fill="#fff" stroke="#a7f3d0"/><text x="750" y="298" font-weight="600">3 · promote</text><text x="750" y="315" font-size="11" fill="#0f766e">package it as a reusable Skill</text>
<rect x="734" y="336" width="320" height="44" rx="9" fill="#fff" stroke="#a7f3d0"/><text x="750" y="354" font-weight="600">4 · hot-reload</text><text x="750" y="371" font-size="11" fill="#0f766e">skill loads live — no restart</text>
</g>
<path d="M894,212 L894,224" stroke="#b45309" stroke-width="1.6" fill="none" marker-end="url(#ag)"/>
<path d="M894,268 L894,280" stroke="#b45309" stroke-width="1.6" fill="none" marker-end="url(#ag)"/>
<path d="M894,324 L894,336" stroke="#b45309" stroke-width="1.6" fill="none" marker-end="url(#ag)"/>
<text x="894" y="404" font-size="11" fill="#047857" text-anchor="middle">the self-improvement flywheel</text>
<text x="44" y="500" font-size="12" fill="#64748b">Read direction widens up the tree (LOCAL → TEAM → GLOBAL); writes to GLOBAL are restricted to the root so shared knowledge stays curated.</text>
<text x="44" y="522" font-size="12" fill="#64748b">An agent never sees another subtree's memory — isolation aligns with the org chart, not with shared storage.</text>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

@@ -0,0 +1,73 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1120 460" font-family="Inter, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif">
<defs>
<filter id="sh" x="-20%" y="-20%" width="140%" height="140%"><feDropShadow dx="0" dy="2" stdDeviation="4" flood-color="#0b1220" flood-opacity="0.10"/></filter>
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#4f46e5"/></marker>
<marker id="ag" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#10b981"/></marker>
<marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#ef4444"/></marker>
<marker id="ay" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#f59e0b"/></marker>
</defs>
<rect width="1120" height="460" fill="#fbfcfe"/>
<text x="44" y="46" font-size="24" font-weight="700" fill="#15181f">Workspace lifecycle — from create to online (and back)</text>
<text x="44" y="72" font-size="13.5" fill="#5b6472">Provisioning is fail-loud: a workspace reaches <tspan font-weight="700" fill="#047857">online</tspan> only after its first heartbeat. Misconfig or timeout lands in <tspan font-weight="700" fill="#b91c1c">failed</tspan>, not a silent default.</text>
<!-- states -->
<g filter="url(#sh)"><rect x="44" y="120" width="150" height="58" rx="11" fill="#f6f4ff" stroke="#7c6df2" stroke-width="1.5"/></g>
<text x="119" y="146" font-size="13" font-weight="700" fill="#3b2fae" text-anchor="middle">create</text>
<text x="119" y="164" font-size="10" fill="#5b6472" text-anchor="middle">POST /workspaces</text>
<g filter="url(#sh)"><rect x="252" y="120" width="160" height="58" rx="11" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.5"/></g>
<text x="332" y="146" font-size="13" font-weight="700" fill="#3730a3" text-anchor="middle">provisioning</text>
<text x="332" y="164" font-size="10" fill="#6366f1" text-anchor="middle">image pull · container · config</text>
<g filter="url(#sh)"><rect x="470" y="120" width="150" height="58" rx="11" fill="#fff7ed" stroke="#f59e0b" stroke-width="1.5"/></g>
<text x="545" y="146" font-size="13" font-weight="700" fill="#b45309" text-anchor="middle">starting</text>
<text x="545" y="164" font-size="10" fill="#92560a" text-anchor="middle">register · await heartbeat</text>
<g filter="url(#sh)"><rect x="678" y="120" width="150" height="58" rx="11" fill="#ecfdf5" stroke="#10b981" stroke-width="1.6"/></g>
<text x="753" y="146" font-size="13" font-weight="700" fill="#047857" text-anchor="middle">online</text>
<text x="753" y="164" font-size="10" fill="#0f766e" text-anchor="middle">serving A2A</text>
<!-- failed -->
<g filter="url(#sh)"><rect x="470" y="250" width="150" height="56" rx="11" fill="#fef2f2" stroke="#ef4444" stroke-width="1.5"/></g>
<text x="545" y="274" font-size="13" font-weight="700" fill="#b91c1c" text-anchor="middle">failed</text>
<text x="545" y="292" font-size="9.5" fill="#7f1d1d" text-anchor="middle">visible error · last_sample_error</text>
<!-- degraded / offline -->
<g filter="url(#sh)"><rect x="678" y="250" width="150" height="56" rx="11" fill="#fffbeb" stroke="#f59e0b" stroke-width="1.4"/></g>
<text x="753" y="274" font-size="13" font-weight="700" fill="#b45309" text-anchor="middle">degraded</text>
<text x="753" y="292" font-size="9.5" fill="#92560a" text-anchor="middle">high error rate</text>
<g filter="url(#sh)"><rect x="886" y="250" width="150" height="56" rx="11" fill="#f1f5f9" stroke="#94a3b8" stroke-width="1.4"/></g>
<text x="961" y="274" font-size="13" font-weight="700" fill="#475569" text-anchor="middle">offline</text>
<text x="961" y="292" font-size="9.5" fill="#64748b" text-anchor="middle">TTL expired</text>
<!-- paused -->
<g filter="url(#sh)"><rect x="886" y="120" width="150" height="58" rx="11" fill="#ffffff" stroke="#cbd5e1" stroke-width="1.4"/></g>
<text x="961" y="146" font-size="13" font-weight="700" fill="#334155" text-anchor="middle">paused</text>
<text x="961" y="164" font-size="10" fill="#64748b" text-anchor="middle">operator-stopped</text>
<!-- happy path arrows -->
<path d="M194,149 L252,149" stroke="#4f46e5" stroke-width="1.8" fill="none" marker-end="url(#a)"/>
<path d="M412,149 L470,149" stroke="#4f46e5" stroke-width="1.8" fill="none" marker-end="url(#a)"/>
<path d="M620,149 L678,149" stroke="#10b981" stroke-width="2" fill="none" marker-end="url(#ag)"/>
<text x="649" y="142" font-size="9.5" fill="#047857" text-anchor="middle">1st ❤</text>
<path d="M828,149 L886,149" stroke="#64748b" stroke-width="1.5" fill="none" marker-end="url(#a)"/><text x="857" y="142" font-size="9" fill="#475569" text-anchor="middle">pause</text>
<!-- fail edges -->
<path d="M332,178 L332,278 L470,278" stroke="#ef4444" stroke-width="1.6" fill="none" stroke-dasharray="5 4" marker-end="url(#ar)"/>
<text x="340" y="232" font-size="10" fill="#b91c1c">runtime/config mismatch</text>
<path d="M545,178 L545,250" stroke="#ef4444" stroke-width="1.6" fill="none" stroke-dasharray="5 4" marker-end="url(#ar)"/>
<text x="552" y="216" font-size="10" fill="#b91c1c">3-min timeout</text>
<!-- online -> degraded/offline + recover -->
<path d="M753,178 L753,250" stroke="#f59e0b" stroke-width="1.5" fill="none" marker-end="url(#ay)"/>
<path d="M828,278 L886,278" stroke="#94a3b8" stroke-width="1.5" fill="none" marker-end="url(#a)"/>
<path d="M886,292 C800,330 720,210 760,180" stroke="#10b981" stroke-width="1.5" fill="none" stroke-dasharray="5 4" marker-end="url(#ag)"/>
<text x="690" y="350" font-size="10.5" fill="#047857">auto-restart → re-register → online</text>
<!-- bottom note -->
<rect x="44" y="360" width="1032" height="68" rx="11" fill="#ecfdf5" stroke="#10b981" stroke-width="1.2"/>
<text x="62" y="384" font-size="12.5" font-weight="700" fill="#047857">Fail-loud, self-healing</text>
<text x="62" y="404" font-size="11.5" fill="#0f766e">A misconfigured runtime fails *visibly* (failed, with last_sample_error) instead of silently booting a default agent. A healthy agent that goes quiet</text>
<text x="62" y="421" font-size="11.5" fill="#0f766e">(offline via TTL) is auto-restarted and re-registers. Paused is an explicit operator action; resume returns it to provisioning.</text>
</svg>

After

Width:  |  Height:  |  Size: 6.4 KiB

+51
View File
@@ -0,0 +1,51 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1120 540" font-family="Inter, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif">
<defs>
<filter id="sh" x="-20%" y="-20%" width="140%" height="140%"><feDropShadow dx="0" dy="2" stdDeviation="4" flood-color="#0b1220" flood-opacity="0.10"/></filter>
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#64748b"/></marker>
<marker id="ar" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#ef4444"/></marker>
</defs>
<rect width="1120" height="540" fill="#fbfcfe"/>
<text x="44" y="46" font-size="24" font-weight="700" fill="#15181f">Registry &amp; heartbeat — how the platform knows an agent is alive</text>
<text x="44" y="72" font-size="13.5" fill="#5b6472">An agent registers on boot, then heartbeats every 30s. A Redis TTL expiring is what flips it offline — no central polling of the data path.</text>
<!-- lanes -->
<text x="150" y="108" font-size="12.5" font-weight="700" fill="#5b5bd6" text-anchor="middle">Workspace agent</text>
<text x="510" y="108" font-size="12.5" font-weight="700" fill="#4f46e5" text-anchor="middle">Platform (Go)</text>
<text x="820" y="108" font-size="12.5" font-weight="700" fill="#15181f" text-anchor="middle">Postgres</text>
<text x="980" y="108" font-size="12.5" font-weight="700" fill="#15181f" text-anchor="middle">Redis</text>
<g stroke="#e2e8f0" stroke-width="1.5">
<line x1="150" y1="118" x2="150" y2="430"/>
<line x1="510" y1="118" x2="510" y2="430"/>
<line x1="820" y1="118" x2="820" y2="430"/>
<line x1="980" y1="118" x2="980" y2="430"/>
</g>
<!-- register -->
<path d="M150,150 L510,150" stroke="#64748b" stroke-width="1.6" fill="none" marker-end="url(#a)"/>
<text x="160" y="143" font-size="11.5" fill="#475569">① POST /registry/register (Agent Card)</text>
<path d="M510,176 L820,176" stroke="#64748b" stroke-width="1.4" fill="none" marker-end="url(#a)"/>
<text x="525" y="169" font-size="10.5" fill="#475569">write Agent Card</text>
<path d="M510,200 L980,200" stroke="#64748b" stroke-width="1.4" fill="none" marker-end="url(#a)"/>
<text x="600" y="193" font-size="10.5" fill="#475569">SET ws:{id}=online · TTL 60s</text>
<path d="M510,224 L152,224" stroke="#22c55e" stroke-width="1.6" fill="none" marker-end="url(#a)"/>
<text x="200" y="217" font-size="11" fill="#16a34a">② one-time auth_token → online · broadcast WORKSPACE_ONLINE</text>
<!-- heartbeat loop -->
<rect x="120" y="248" width="900" height="92" rx="11" fill="#f8fafc" stroke="#cbd5e1" stroke-dasharray="5 4"/>
<text x="138" y="270" font-size="12" font-weight="700" fill="#334155">every 30s — heartbeat loop</text>
<path d="M150,294 L510,294" stroke="#64748b" stroke-width="1.6" fill="none" marker-end="url(#a)"/>
<text x="160" y="287" font-size="11" fill="#475569">③ POST /registry/heartbeat (error_rate · active_tasks · uptime)</text>
<path d="M510,318 L980,318" stroke="#64748b" stroke-width="1.4" fill="none" marker-end="url(#a)"/>
<text x="600" y="311" font-size="10.5" fill="#475569">refresh TTL 60s · evaluate degraded threshold</text>
<!-- offline via TTL expiry -->
<path d="M980,380 L514,380" stroke="#ef4444" stroke-width="1.8" fill="none" marker-end="url(#ar)"/>
<text x="560" y="373" font-size="11.5" fill="#b91c1c">④ no heartbeat → TTL expires → Redis keyspace event</text>
<path d="M510,404 L824,404" stroke="#ef4444" stroke-width="1.4" fill="none" marker-end="url(#ar)"/>
<text x="540" y="421" font-size="11" fill="#b91c1c">platform marks status=offline · broadcasts WORKSPACE_OFFLINE (node greys out)</text>
<!-- note -->
<rect x="44" y="456" width="1032" height="62" rx="11" fill="#eef2ff" stroke="#4f46e5" stroke-width="1.2"/>
<text x="62" y="480" font-size="12.5" font-weight="700" fill="#3730a3">Why TTL-driven?</text>
<text x="62" y="500" font-size="11.5" fill="#4338ca">Liveness is push-based: a crashed or partitioned agent simply stops refreshing its key, and expiry flips it offline automatically — the platform never sits in the agent-to-agent data path. Health is also probed proactively (Docker sweep) and reactively (A2A errors); all paths converge on the same offline → auto-restart handler.</text>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

+39
View File
@@ -0,0 +1,39 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1040 440" font-family="Inter, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif">
<defs>
<filter id="sh" x="-20%" y="-20%" width="140%" height="140%"><feDropShadow dx="0" dy="2" stdDeviation="4" flood-color="#0b1220" flood-opacity="0.10"/></filter>
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="9" markerHeight="9" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#10b981"/></marker>
</defs>
<rect width="1040" height="440" fill="#fbfcfe"/>
<text x="44" y="46" font-size="24" font-weight="700" fill="#15181f">Skills &amp; the self-improvement loop</text>
<text x="44" y="72" font-size="13.5" fill="#5b6472">A skill is a reusable recipe (a <tspan font-family="monospace" fill="#0369a1">SKILL.md</tspan> + optional tools). Agents capture what works as memory, then promote proven patterns into skills that hot-reload.</text>
<!-- circular 4-step loop -->
<g filter="url(#sh)"><rect x="360" y="118" width="320" height="56" rx="11" fill="#fff7ed" stroke="#f59e0b" stroke-width="1.5"/></g>
<text x="520" y="142" font-size="13.5" font-weight="700" fill="#b45309" text-anchor="middle">1 · Capture — write a memory</text>
<text x="520" y="160" font-size="11" fill="#92560a" text-anchor="middle">agent records a fact or how-to during work</text>
<g filter="url(#sh)"><rect x="724" y="200" width="280" height="56" rx="11" fill="#eff6ff" stroke="#3b82f6" stroke-width="1.5"/></g>
<text x="864" y="224" font-size="13.5" font-weight="700" fill="#1d4ed8" text-anchor="middle">2 · Signal — it works, repeatedly</text>
<text x="864" y="242" font-size="11" fill="#1e40af" text-anchor="middle">same approach succeeds across tasks</text>
<g filter="url(#sh)"><rect x="360" y="284" width="320" height="56" rx="11" fill="#ecfdf5" stroke="#10b981" stroke-width="1.5"/></g>
<text x="520" y="308" font-size="13.5" font-weight="700" fill="#047857" text-anchor="middle">3 · Promote — package as a Skill</text>
<text x="520" y="326" font-size="11" fill="#0f766e" text-anchor="middle">SKILL.md (+ tools/) added to the workspace</text>
<g filter="url(#sh)"><rect x="36" y="200" width="280" height="56" rx="11" fill="#f6f4ff" stroke="#7c6df2" stroke-width="1.5"/></g>
<text x="176" y="224" font-size="13.5" font-weight="700" fill="#3b2fae" text-anchor="middle">4 · Hot-reload — live, no restart</text>
<text x="176" y="242" font-size="11" fill="#5b3fc4" text-anchor="middle">file watcher injects it into the prompt</text>
<!-- loop arrows -->
<path d="M680,150 C740,160 760,180 800,200" stroke="#10b981" stroke-width="2" fill="none" marker-end="url(#a)"/>
<path d="M820,256 C780,290 720,300 680,306" stroke="#10b981" stroke-width="2" fill="none" marker-end="url(#a)"/>
<path d="M360,318 C260,320 220,280 200,256" stroke="#10b981" stroke-width="2" fill="none" marker-end="url(#a)"/>
<path d="M210,200 C260,160 300,150 360,146" stroke="#10b981" stroke-width="2" fill="none" marker-end="url(#a)"/>
<text x="520" y="232" font-size="12" font-weight="700" fill="#16a34a" text-anchor="middle">agent gets durably</text>
<text x="520" y="250" font-size="12" font-weight="700" fill="#16a34a" text-anchor="middle">better over time</text>
<!-- where skills come from -->
<rect x="44" y="360" width="952" height="62" rx="11" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.2"/>
<text x="62" y="384" font-size="12.5" font-weight="700" fill="#15181f">Skills come from three places</text>
<text x="62" y="404" font-size="11.5" fill="#475569">• workspace-local <tspan font-family="monospace">skills/</tspan> • plugin-mounted shared skills/rules • this promotion loop. All are hot-reloadable, and peers can see a skill's description via the Agent Card.</text>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

+71
View File
@@ -0,0 +1,71 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1120 520" font-family="Inter, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif">
<defs>
<filter id="sh" x="-20%" y="-20%" width="140%" height="140%"><feDropShadow dx="0" dy="2" stdDeviation="4" flood-color="#0b1220" flood-opacity="0.10"/></filter>
</defs>
<rect width="1120" height="520" fill="#fbfcfe"/>
<text x="44" y="46" font-size="24" font-weight="700" fill="#15181f">Workspace tiers — escalating capability &amp; isolation (T1T4)</text>
<text x="44" y="72" font-size="13.5" fill="#5b6472">A workspace's <tspan font-family="monospace" fill="#0369a1">tier</tspan> sets its resource budget and which tools it may use. Higher tier = more power, less sandboxing — assign the lowest tier that does the job.</text>
<!-- four tier columns -->
<!-- T1 -->
<g filter="url(#sh)"><rect x="44" y="104" width="252" height="360" rx="14" fill="#f0fdf4" stroke="#22c55e" stroke-width="1.6"/></g>
<text x="66" y="136" font-size="18" font-weight="700" fill="#15803d">T1</text>
<text x="104" y="136" font-size="14" font-weight="700" fill="#166534">Sandboxed</text>
<text x="66" y="160" font-size="11.5" fill="#15803d">most restricted</text>
<g font-size="12" fill="#14532d">
<text x="66" y="196">Tools: core only</text>
<text x="66" y="222" fill="#166534">✓ delegate · memory</text>
<text x="66" y="244" fill="#166534">✓ peer messaging</text>
<text x="66" y="270" fill="#9ca3af">✕ browser</text>
<text x="66" y="292" fill="#9ca3af">✕ computer / host</text>
</g>
<text x="66" y="332" font-size="11.5" fill="#15803d">Best for: reasoning,</text>
<text x="66" y="350" font-size="11.5" fill="#15803d">coordination, writing</text>
<text x="66" y="392" font-size="10.5" fill="#16a34a">lowest resource budget</text>
<!-- T2 -->
<g filter="url(#sh)"><rect x="308" y="104" width="252" height="360" rx="14" fill="#eff6ff" stroke="#3b82f6" stroke-width="1.6"/></g>
<text x="330" y="136" font-size="18" font-weight="700" fill="#1d4ed8">T2</text>
<text x="368" y="136" font-size="14" font-weight="700" fill="#1e40af">Standard</text>
<text x="330" y="160" font-size="11.5" fill="#1d4ed8">the common default</text>
<g font-size="12" fill="#1e3a8a">
<text x="330" y="196">Tools: T1 +</text>
<text x="330" y="222" fill="#1d4ed8">✓ browser</text>
<text x="330" y="244" fill="#1d4ed8">✓ web access</text>
<text x="330" y="270" fill="#9ca3af">✕ computer / host</text>
</g>
<text x="330" y="332" font-size="11.5" fill="#1d4ed8">Best for: research,</text>
<text x="330" y="350" font-size="11.5" fill="#1d4ed8">content, most agents</text>
<text x="330" y="392" font-size="10.5" fill="#3b82f6">moderate budget</text>
<!-- T3 -->
<g filter="url(#sh)"><rect x="572" y="104" width="252" height="360" rx="14" fill="#fff7ed" stroke="#f59e0b" stroke-width="1.6"/></g>
<text x="594" y="136" font-size="18" font-weight="700" fill="#b45309">T3</text>
<text x="632" y="136" font-size="14" font-weight="700" fill="#92400e">Privileged</text>
<text x="594" y="160" font-size="11.5" fill="#b45309">elevated access</text>
<g font-size="12" fill="#78350f">
<text x="594" y="196">Tools: T2 +</text>
<text x="594" y="222" fill="#b45309">✓ computer use</text>
<text x="594" y="244" fill="#b45309">✓ broader system access</text>
</g>
<text x="594" y="332" font-size="11.5" fill="#b45309">Best for: GUI automation,</text>
<text x="594" y="350" font-size="11.5" fill="#b45309">heavier dev work</text>
<text x="594" y="392" font-size="10.5" fill="#f59e0b">higher budget</text>
<!-- T4 -->
<g filter="url(#sh)"><rect x="836" y="104" width="240" height="360" rx="14" fill="#fef2f2" stroke="#ef4444" stroke-width="1.6"/></g>
<text x="858" y="136" font-size="18" font-weight="700" fill="#b91c1c">T4</text>
<text x="896" y="136" font-size="14" font-weight="700" fill="#991b1b">Full Access</text>
<text x="858" y="160" font-size="11.5" fill="#b91c1c">least sandboxed</text>
<g font-size="12" fill="#7f1d1d">
<text x="858" y="196">Tools: T3 +</text>
<text x="858" y="222" fill="#b91c1c">✓ full host access</text>
<text x="858" y="244" fill="#b91c1c">✓ Docker socket</text>
</g>
<text x="858" y="332" font-size="11.5" fill="#b91c1c">Best for: infra/ops agents</text>
<text x="858" y="350" font-size="11.5" fill="#b91c1c">that manage other workspaces</text>
<text x="858" y="392" font-size="10.5" fill="#ef4444">highest budget · use sparingly</text>
<!-- gradient bar -->
<text x="44" y="498" font-size="12" fill="#64748b">Every tier still runs on its own isolated machine; tier controls in-machine capability &amp; budget. <tspan font-weight="600" fill="#15181f">Tools are gated</tspan>: browser needs ≥ T2, computer-use needs ≥ T3.</text>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB