Agents observe the system and automatically create capsules when work should be done. They do not bypass FRAME: all work flows through FRAME_CAPSULE.createCapsule, FRAME_CAPSULE.signCapsule, and FRAME_CAPSULE_NETWORK.announceCapsule, then the normal scheduler and execution pipeline.
- Layer: Above intent execution. Agents produce capsules; the capsule scheduler and executor handle placement and execution.
- Dependencies: Context memory, capability table, capsule store, identity, capsule API, capsule network.
- No bypass: Agents never call
FRAME.handleIntentdirectly for their own tasks; they create signed capsules and announce them.
Each agent is a simple object with three methods:
- observe() — Returns a snapshot of relevant system state (e.g. rolling context, capability table, capsule queue).
- decide(observation) — Returns an action object, or
nullif no action should be taken. - act(action) — Creates a capsule from the action, signs it, and announces it. Returns a Promise (resolves to
{ announced, capsuleId }or similar).
Flow: observe → decide → act. The engine runs this loop for every registered agent on a fixed interval (every 5 seconds). If decide returns non-null, the engine calls act(decision) and respects a per-agent cooldown (30 seconds) before allowing another act from the same agent.
File: ui/system/agentEngine.js
- runAgents() — Loads agents from
FRAME_AGENT_REGISTRY.getAgents(). For each agent: if cooldown elapsed, callobserve(), thendecide(observation). If decision is non-null, setagent.lastRun = now, callact(decision)(and optionally log resolution for capsule id). - start() — Starts the loop: run once immediately, then every 5 seconds (
LOOP_INTERVAL_MS). - stop() — Clears the interval.
- registerAgent(agent) — Delegates to
FRAME_AGENT_REGISTRY.register(agent). - getActivityLog() — Returns recent entries:
{ type: 'decision'|'capsule'|'error', agentId, decision?, capsuleId?, message?, timestamp }(used by the Agent Activity widget).
Cooldown: Minimum 30 seconds (COOLDOWN_MS) between act() calls per agent; enforced by checking agent.lastRun before calling act.
File: ui/system/agentRegistry.js
- register(agent) — Requires
agent.id(string) andobserve,decide,act(functions). Replaces existing agent with same id, or appends. Returns boolean. - getAgents() — Returns a copy of the registered agents array.
Built-in agents register themselves when their script runs (e.g. FRAME_AGENT_REGISTRY.register({ id: '...', observe, decide, act })).
Agents build capsules with:
- FRAME_CAPSULE.createCapsule({ ... }) — Fields:
originIdentity(fromFRAME_IDENTITY.getCurrent()),requestedCapability,payload(e.g.{ action, payload }),paymentRule: { type: 'credit', amount: 1 },privacyRule: 'public',executionPolicy: { maxRetries: 2, timeout: 10000 }. - FRAME_CAPSULE.signCapsule(capsule) — Sets
capsule.idandcapsule.signature; returns Promise. - FRAME_CAPSULE_NETWORK.announceCapsule(signedCapsule) — Sends the capsule through the scheduler (local or single peer) or broadcast. Returns Promise.
So act(decision) is async: get current identity → createCapsule → signCapsule → announceCapsule, and return the resulting Promise. The engine does not await act in a way that blocks the loop; it only attaches a .then to log capsule id when the announcement resolves.
- Cooldown: 30 seconds between
act()per agent to avoid duplicate capsules in quick succession. - lastRun: Each agent may have
agent.lastRunset by the engine after eachact(); the engine skipsact()if(now - agent.lastRun) < COOLDOWN_MS. - No direct execution: Agents do not invoke the intent pipeline directly; all execution goes through capsules and the normal scheduler/executor.
- Activity log: Decisions and capsule creations (and errors) are logged for the Agent Activity widget and debugging.
All live under ui/system/agents/.
| Agent | File | Purpose |
|---|---|---|
| Context Analyzer | contextAnalyzerAgent.js |
observe: FRAME_CONTEXT_MEMORY.getRollingContext(). decide: activity spike (≥8 events in window) or many similar actions (≥3 same action) → { type: 'analyze_context', payload: { events } }. act: create capsule requestedCapability: 'ai.analyze', payload { action: 'ai.analyze', events }, announce. |
| Capability Discovery | capabilityDiscoveryAgent.js |
observe: FRAME_CAPABILITY_TABLE.getAllProviders() keys. decide: if capability set changed (new or disappeared) → { type: 'update_capability_map' }. act: create capsule requestedCapability: 'network.capability_map', announce. |
| System Health | systemHealthAgent.js |
observe: capsule queue (pending/announced/executing count), connections, peers. decide: if queue ≥ 5 → { type: 'load_distribution' }. act: create capsule requestedCapability: 'compute.redistribute', announce. |
| AI Assistant | aiAssistantAgent.js |
observe: recent rolling context. decide: repeated commands (same action ≥2) or intent-like queries (≥2) → { type: 'assist_user' }. act: create capsule requestedCapability: 'ai.assist', announce. |
- Register a new agent: Implement an object with
id,observe,decide,act, and callFRAME_AGENT_REGISTRY.register(agent)(e.g. from a script loaded after the registry and engine). The engine will pick it up on the next run. - Script order: In
index.html, loadagentRegistry.js, thenagentEngine.js, then each agent script so that agents register beforeFRAME_AGENT_ENGINE.start()is called fromapp.js.
app.js: After the capability advertiser is started, the boot sequence calls FRAME_AGENT_ENGINE.start() so the agent loop runs (every 5 seconds) for the rest of the session.
- Data source:
agent.activity. UsesFRAME_AGENT_ENGINE.getActivityLog(); each entry shown as agent id (label) and type/capsule id/decision/error (value). Last 20 entries. - Default widget:
default_agent_activity, title "Agent Activity", data sourceagent.activity, refresh 5s, priority 52, region sidebar.
| File | Purpose |
|---|---|
ui/system/agentRegistry.js |
register(agent), getAgents(). |
ui/system/agentEngine.js |
start/stop, runAgents (observe → decide → act), cooldown, activity log. |
ui/system/agents/contextAnalyzerAgent.js |
Context memory patterns → ai.analyze capsule. |
ui/system/agents/capabilityDiscoveryAgent.js |
Capability table changes → network.capability_map capsule. |
ui/system/agents/systemHealthAgent.js |
Capsule backlog → compute.redistribute capsule. |
ui/system/agents/aiAssistantAgent.js |
Repeated/incomplete user activity → ai.assist capsule. |
Integration: app.js (start engine after boot), widgetManager (agent.activity data source, default_agent_activity widget).