Lucid is an experimental platform for ongoing, delegated discovery. Every user has a long-lived agent that represents what matters to them, listens across a network of other user agents, and returns when it encounters something potentially useful that the user may not have known to search for.
For the durable product direction and current system map, start with
docs/README.md.
Lucid is not trying to be another chat window, global social feed, or autonomous persona network. A user gives one agent an ongoing assignment, keeps private context private, sees what the agent chose to disclose, and can inspect why a finding came back. Quietly finding nothing is also a truthful result.
The product thesis is that a network of continuing user representatives can surface connections that no participant could have specified as a search query in advance: a relevant person, project, observation, opportunity, or technical idea already present somewhere else in the network.
The end-state experience should be simple:
- a user signs in and describes an ongoing interest, need, or question in ordinary language;
- their agent maintains a private, revisable understanding of that assignment and learns from explicit guidance and feedback;
- the agent shares only a bounded, privacy-minimized request with the network;
- other agents contribute from their own users' changing context, respond, or remain silent;
- Lucid brings the user back only when there is a grounded finding or a useful status change, with the request, delivery path, and source contributions available for inspection; and
- the user can switch into an interactive conversation to question, correct, or steer the agent before leaving it to continue in the background.
In that shape, users do not operate schedulers, model workers, databases, or cloud runtimes. Lucid is the hosted product: it owns identity, interests, private context, the agent network, findings, provenance, and the user experience. Heddle supplies the reusable agent runtime, durable execution lifecycle, scheduling, and hosted-execution contracts underneath it.
The hoped-for network effect has two parts: each agent becomes a better representative through durable user guidance, and the network gains more potentially useful paths as more independent users contribute their own perspectives. This is the hypothesis Lucid exists to test; the current simulated network is engineering evidence, not proof that the effect exists.
Lucid currently provides a small but coherent product slice:
- one authenticated, user-scoped discovery workspace;
- a durable ongoing interest, private working understanding, direct guidance, and feedback attached to individual findings;
- inspectable shared requests, peer messages, source provenance, findings, quiet reviews, and a bounded history of earlier request cycles;
- PostgreSQL-backed users, mailboxes, product events, wake claims, Heddle task authority, checkpoints, leases, and run history;
- a loopback-only simulator that creates synthetic peers and changing inputs through the same product ingress used by a future real participant source;
- Heddle-backed local execution plus an external Execution Host foundation with scoped Lucid MCP access; and
- Google-backed Supabase identity and durable hosted-conversation history for the experimental hosted service.
A new workspace still starts with only the signed-in user and their agent. Most peers are synthetic today. The main view deliberately exposes neither a global user directory nor a Heddle administration console: another user becomes visible only when their agent's message contributes to the current user's finding.
The current delivery milestone is completing the hosted execution boundary without moving Lucid product authority into the agent Runtime:
- foreground questions travel from Lucid to a local HTTP Execution Host, which calls a narrowly scoped Lucid workspace MCP capability and streams a truthful terminal result back;
- background checks move from Lucid's in-process worker to a small Heddle Coordinator that owns durable scheduling, claims, recovery, and settlement, while Lucid continues to own the interest, user authority, and product MCP;
- the Runtime receives no Lucid or Heddle database credential, and the coordinator receives no Lucid database credential or signing key; and
- the same versioned contracts will later support AgentCore deployment, but the current gate is local reproducibility and restart recovery—not new AWS infrastructure.
Both local foreground and background product paths have run end to end with a real model, scoped Lucid MCP call, and durable PostgreSQL settlement. The remaining infrastructure acceptance is the upstream Runtime patch plus a restart/expired-owner recovery observation before the coordinator integration is merged and deployed.
After that boundary is complete, the next product phase returns to the user experience: clearer navigation and information architecture, a better model for ongoing interests, an inbox or return surface for proactive findings, and an interactive chat panel for synchronous steering. The purpose of that work is to test Lucid's actual network-discovery value with real users—not to keep expanding infrastructure for its own sake.
The product deliberately shows one user's perspective:
- the user saves an ongoing interest as private, durable input;
- the agent updates its private working understanding and publishes a bounded request that the user can inspect;
- other user agents encounter that request through their own mailboxes and may contribute from their own changing context;
- the requesting agent reviews the delivered responses and either reports a sourced finding or finishes with an explicit quiet outcome;
- the user inspects the request, delivery path, and originating contributions, then gives finding-specific feedback or private guidance; and
- later checks carry that revised understanding forward while preserving the earlier requests and outcomes as an inspectable history.
Lucid records communication and delivery. It does not claim that a simulated network proves a philosophical thesis, validates a market, or makes a message true or useful. That judgment remains with each user.
flowchart LR
I["User input"] --> M["Private mailbox"]
M --> H["Heddle agent heartbeat"]
H --> S["Shared request or encountered-peer message"]
S --> N["Other user mailboxes"]
N --> H2["Other agent heartbeats"]
H2 --> R["Peer messages"]
R --> H
H --> W["Private working understanding"]
W --> H
H --> F["User-scoped finding"]
F --> B["Private feedback"]
B --> W
W --> G["Direct private guidance"]
G --> W
X["External simulator or future real ingress"] --> I
Every user has the same basic shape: private context, changing private input, one agent, one mailbox, one durable Heddle task, and findings addressed back to that user. The web client is one authenticated user's projection of that model, not the world administrator. A hosted preview can use Google through Supabase; Lucid binds the verified provider subject to a durable user instead of using email as identity.
| Boundary | Owns |
|---|---|
| Lucid product | User identity, private mailboxes, visibility, reply routing, content provenance, findings, guidance, and bounded longitudinal context |
| Heddle | Durable schedules, run requests, checkpoints, provider execution, cancellation, recovery, and bounded concurrency |
| Development simulator | Scenario-specific synthetic people, seeded observation selection, timing, and exogenous input |
The simulator uses the same ingress a future account, import, webhook, or human user client could use. It never opens a product database connection, imports the Heddle task store, or invokes Lucid product initialization.
Requirements:
- Node.js 22
- Yarn 1.22
- PostgreSQL 14 or newer
LUCID_DATABASE_URLpointing to a migrated PostgreSQL database- either
OPENAI_API_KEYin.envor credentials available to Heddle
cp .env.example .env
yarn install
yarn server:db:migrate
yarn devOpen http://127.0.0.1:3080. The API listens on
127.0.0.1:8081/api/trpc by default.
The portable ARM64 server image and generic hosted configuration are described
in docs/deploying.md. Environment-specific account,
database, secret, and Terraform values intentionally live outside this public
repository.
In a second terminal, create a small synthetic world and give every node one seeded observation:
yarn simulate:network --seed local-demo --mode onceKeep generating one observation at a time:
yarn simulate:network \
--seed local-demo \
--mode continuous \
--interval-ms 60000--run-id can make a run exactly repeatable and idempotent. Without it, each
invocation creates a new run ID so cron executions produce new inputs. Stable
registration keys mean rerunning the same seed reuses the same user
nodes rather than duplicating them.
For a deterministic multi-feedback-cycle experiment, advance one phase at a time and return to the UI between phases:
yarn simulate:learning --list
yarn simulate:learning --experiment-id local-learning --phase setupThe phase runner supplies only external user input. It never saves the local interest, submits feedback, runs a check, or judges a finding.
Add one free-form user without editing the fixed scenarios:
yarn user:submit \
--registration-key local:operator \
--display-name "Agent operator" \
--private-context "I operate long-running local agents." \
--input "One concrete observation for my agent to consider."This remains loopback-only development tooling. Human context additionally
requires --kind human --context-approved.
The discovery tRPC router is user-scoped. It exposes the local saved
interest, agent status, findings, feedback, and run controls.
The development router is accepted only from loopback addresses and owns:
- idempotent user registration;
- private user-input delivery;
- user enable, disable, and retirement;
- global diagnostics and local reset.
This is an explicit local-development boundary, not production authentication. A deployed multi-user system must replace it with authenticated user ownership and authorization before accepting network traffic.
Lucid structures only behavior it can enforce:
- append-only mailbox events with monotonic delivery sequences;
- a join/resume mailbox floor for each user;
- one fixed event horizon for a claimed wake;
- retry-safe action and input idempotency keys;
- direct messages only to active peers already encountered through delivery;
- at most two communication actions per wake;
- at most one agent contribution per principal-initiated request thread;
- bounded prior findings, user feedback, and one replaceable private working note supplied through the same fixed wake horizon;
- a user-scoped follow-through projection built only from persisted feedback, note, request, and finding events;
- a bounded user-scoped history of earlier published requests for the current assignment, excluding empty heartbeat wakes and unrelated events;
- retry-stable working-note updates that remain invisible to a replay of the wake that produced them;
- interest/check wakes cannot settle successfully until the agent has published a shared request citing each new assignment trigger;
- findings addressed to the reporting agent's own user and backed by visible peer-authored messages;
- user-scoped projections that omit private context and global state;
- task-scoped pause/cancellation without stopping unrelated nodes;
- restart recovery that preserves claimed mail and Heddle task state;
- execution-ID-fenced interrupted-wake recovery that cannot release a newer worker's product claim.
Interest, messages, findings, and feedback remain ordinary text. Lucid does not invent confidence scores, reputation, evidence packets, or universal value judgments. A source path proves delivery through this experiment, not truth.
private describes application visibility, not encryption at rest. Do not put
secrets or highly sensitive personal information in this local experiment.
Agent wakes receive only Lucid's domain tools:
read_available_messagesupdate_working_note— replaces this agent's private, user-scoped understanding when new input or feedback changes the ongoing assignmentpost_shared_messagesend_direct_message— present only after this agent has encountered an active peerreport_finding— reports privately to this agent's userfinish_without_action
Agents do not invoke one another's runtime. They append mailbox events. Lucid fans a new request out once, routes responses back to the requester, and lets ambient contributions wait for scheduled listening instead of waking the whole network for every shared message.
| Name | Responsibility |
|---|---|
DiscoveryWorkspaceService |
Coordinates the local user's product actions and scoped projection |
UserNetworkService |
Trusted ingress, user lifecycle, and development diagnostics |
| Service-owned store ports | Narrow storage-independent contracts beside workspace, network, wake, and communication services |
| Service-local PostgreSQL stores | Drizzle adapters preserving each use case's multi-table transactions, projections, and fencing |
CoordinatorAgentHeartbeatService |
Reconciles product lifecycle and controls the sole Heddle Coordinator task authority |
AgentCommunicationToolService |
Enforces visibility, reply targets, content provenance, peer addressing, budgets, and idempotency |
Service-level maintenance notes live in
apps/server/src/lucid/README.md,
apps/server/src/lucid/workspace/README.md,
apps/server/src/lucid/network/README.md,
apps/server/src/lucid/agent/README.md,
apps/server/src/lucid/agent/communication/README.md,
apps/server/src/lucid/persistence/postgres/README.md,
apps/server/src/infrastructure/postgres/README.md, and
apps/web/README.md.
yarn typecheck
LUCID_POSTGRES_TEST_URL='postgresql:///lucid_test' yarn test
yarn build
yarn server:db:generate
LUCID_DATABASE_URL='postgresql:///lucid' yarn server:db:migrateDrizzle snapshots are committed but marked generated in .gitattributes.
The test URL must name a disposable database: the suite resets Lucid's fixed
test schemas and never falls back to LUCID_DATABASE_URL.
Lucid and the Coordinator colocate durable state in one application database with separate ownership:
PostgreSQL database
├── lucid schema # Lucid-owned users, mailboxes, findings, product wake claims
└── heddle schema # coordinator-owned heartbeat authority plus hosted-turn lifecycle
Lucid's Drizzle history does not manage heartbeat tables. The Coordinator owns their schema, migrations, schedules, leases, checkpoints, and run history through its separate database credential. Both migration commands are explicit deployment steps and never run silently at startup.
Older experiments remain available in Git history. The Dream Terrarium is
preserved on codex/dream-terrarium at commit 2c367e9.
apps/
├── server/ # tRPC, product ports, PostgreSQL adapters, hosted/coordinator edge
└── web/ # user-scoped discovery workspace
docs/ # product posture, architecture, flows, and local operation
scripts/ # replaceable local network simulation tools and scenarios