Redis Streams Contract¶
This page DOCUMENTS the stream topology. It is NOT the source of truth.
AUTHORITATIVE SOURCE: config/dolly-routing.yaml (for stream names and routing rules) AUTHORITATIVE SOURCE: config/ports.yaml (for Redis connection details)
Code that uses a stream name MUST read it from config/dolly-routing.yaml or use the constant defined in the executor code. Code MUST NOT hardcode stream names as string literals.
Connection¶
Host: redis.ge-system.svc.cluster.local (k8s service DNS) Port: DEFINED IN config/ports.yaml (currently 6381 as of 2026-02-14) Password: from Vault at ge/redis StatefulSet: redis-0 in ge-system namespace
Stream Topology (as documented in INFRA-OVERVIEW 2026-02-14)¶
Agent Triggers¶
Pattern: triggers.{team}.{agent_name} (team-bound agents) or triggers.{agent_name} (shared agents)
Consumer group: executor-group
One stream per registered agent per team (team-bound agents get per-team streams; shared agents keep a single stream)
Authoritative list of agents: ge-ops/master/AGENT-REGISTRY.json
Work Completion¶
Stream: ge:work:completed Published by: PLANNED (not yet implemented) — executor currently writes COMP-*.md files, host cron syncs to DB. ge-orchestrator listens on this stream but nothing publishes to it yet.
System¶
Stream: system.halt -- HALT broadcasts (all agents subscribe) Stream: system.health -- Health check heartbeats
Notifications¶
Stream: notifications.queue -- Portal notification routing
Decisions¶
Stream: decisions.pending -- Human decisions awaiting response Stream: decisions.resolved -- Resolved decisions
Triad Coordination (ge:triad:*)¶
System-level coordination streams for the autonomous reviewer↔executor↔DJ cycle.
Not agent-trigger streams — registered under coordination_streams: in
config/dolly-routing.yaml (not as per-agent redis_stream:).
| Stream | Direction | MAXLEN | Consumer group |
|---|---|---|---|
ge:triad:to-executor |
reviewer/DJ → executor | 500 | triad-executor-group |
ge:triad:to-reviewer |
executor/DJ → reviewer | 500 | triad-reviewer-group |
ge:triad:to-dj |
reviewer → DJ inbox | 100 | triad-dj-group |
- MAXLEN is a per-stream cap (≤1000 for system-level streams) per DEC-20260529-A — 500/500/100 is conformant; the sum (1100) is NOT an aggregate violation.
- Bodies > 2KB spill to sidecar files (
/home/claude/triad-messages/<correlation_id>.md); the stream carries acontent_pathpointer. - Full message schema + polling + DJ-inbox design:
ge-ops/wiki/docs/development/roadmaps/triad-broker-v1-design.md(§4 streams, §5 schema, §6 polling). - Created by
scripts/triad/setup-streams.sh(idempotent;XGROUP CREATEBUSYGROUP treated as no-op).
Message Format (Agent Triggers)¶
Reference format from INFRA-OVERVIEW. Verify against actual executor code at ge_agent/runner.py:
{
"trigger_id": "trig-{ISO-date}-{sequence}",
"timestamp": "{ISO-8601}",
"work_item": "{path to work item or task reference}",
"context": {
"client": "{client-slug}",
"project": "{project-slug}",
"team": "alpha|beta"
},
"triggered_by": "{agent_name|system|TaskService}",
"reason": "{trigger_reason}"
}
Consumer Group Configuration¶
The shared executor uses Redis consumer groups to ensure each trigger is delivered to exactly one pod:
- Group name:
executor-group(all executor pods share this group) - Consumer name:
$POD_NAME(unique per pod, from k8s downward API) - Read mode:
XREADGROUPwith>(new messages only for each consumer) - ACK: after execution completes (success or failure)
- Orphan recovery: on startup, each pod claims and ACKs messages from dead consumers (idle > 60s) to prevent pending message buildup from pod restarts
- Dedup:
exec_dedup:{project_id}:{work_item_id}Redis key with 5-min TTL prevents double execution even if the same trigger is delivered twice
Source of truth: ge_agent/listener.py
Rules¶
- ALL XADD calls MUST include MAXLEN. Cap is per-stream (per DEC-20260529-A): ~100 for agent-scoped (
triggers.*) streams; ≤1000 for system-level (ge:platform:*,ge:triad:*) streams. NOT an aggregate budget. - New streams require registration in config/dolly-routing.yaml BEFORE code is written (agent-trigger streams as per-agent
redis_stream:; non-agent system streams undercoordination_streams:) - Dedup on work_item_id with 5-min window prevents double execution
- Max hook chain depth: 3 (tasks that create tasks that create tasks)
- Hook depth: 1 for no_block tier
- Monitoring agent isolation: see hook-loops pitfall