refactor(agenetes): address durable threads by globally unique threadId
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 146
- Forks
- 20
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 43
Description
Summary
Refactor Agenetes so a durable thread is identified and addressed solely by its globally unique threadId. Namespace remains an internal persistence-placement concept that preserves per-Space physical storage; it must not remain part of the public thread identity or be required repeatedly by query and invocation callers.
This is a legacy cleanup, not a prerequisite for the long-horizon task capability in docs/proposals/long-horizon-tasks.md. Huabu can continue deriving the current Canvas namespace inside its composition adapters while the refactor is pending.
Current problem
The current implementation has inconsistent identity surfaces:
- live handles are addressed globally by
threadId; - durable records, history, event tails, and forks require
(Namespace, threadId); Namespaceincludes optional storage configuration such asstorage.root, so a persistence implementation detail leaks into general thread APIs;- callers reconstruct the same Canvas namespace repeatedly even though the thread's storage placement was fixed when the workload was created.
The namespace parameter exists to preserve the historical per-Space storage layout and forward compatibility. It should not redefine thread identity as a composite key.
Desired model
threadId
-> durable thread locator: threadId -> namespaceId
-> namespace registry/resolver: namespaceId -> Namespace storage configuration
-> per-namespace ThreadStore / EventLogStore / TurnStore
threadIdis the globally unique thread identity and the only address required by thread query, recovery, control, and invocation APIs.- Creating a durable workload supplies a trusted
namespaceIdto select persistence placement. - Agenetes durably binds the new
threadIdto that namespace and resolves storage internally on later access. - Namespace configuration is registered or resolved by the trusted host composition layer; callers cannot inject
storage.rootinto ordinary thread operations. - Existing per-Space on-disk storage remains supported.
Expected API direction
Thread-oriented operations should converge on shapes such as:
record(threadId)
history(threadId)
tail(threadId)
get(threadId)
close(threadId)
invoke(threadId, submission)
The exact locator and namespace-registry contracts should be designed before implementation. This issue does not require adding invoke if that operation is not otherwise ready; it requires any eventual invocation surface to follow the same identity rule.
Compatibility and migration requirements
- Preserve existing thread records and conversation logs stored under each Space's
.historydirectory. - Add a durable or deterministically rebuildable thread locator without scanning every namespace on each lookup.
- Migrate or compatibly read persisted
WorkloadSpec.namespacerecords while preserving their namespace assignment. - Keep namespace assignment immutable for an existing thread unless a future explicit storage migration is designed.
- Ensure cold recovery resolves the same persisted workload and conversation using only
threadId. - Retain fail-fast handling for duplicate or conflicting global thread IDs.
Acceptance criteria
- Public Agenetes thread lookup/query/control APIs no longer require a
Namespaceobject. - A durable thread can be cold-located and recovered from
threadIdalone. - Namespace storage configuration is resolved internally from trusted registration or host wiring.
- Existing per-Space thread, event, and turn files remain readable without data loss.
- Live and durable surfaces use the same global
threadIdidentity rule. - Huabu call sites no longer reconstruct and pass a Namespace for every thread operation.
- The identity and storage-placement distinction is documented in the Agenetes architecture.
Non-goals
- Combining
namespaceIdandthreadIdinto a composite Thread identity. - Moving all conversations into one global storage directory.
- Changing Agent Node identity or the Canvas ownership of a thread.
- Blocking long-horizon Agent Node creation, recursive delegation, or headless invocation work.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing the Agenetes thread lookup, recovery, control, and invocation APIs, then inspect Huabu call sites that reconstruct and pass Namespace values. Read docs/proposals/long-horizon-tasks.md for the stated boundary, and use the acceptance criteria to verify threadId-only recovery, preserved per-Space files, compatibility, and documented identity rules.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, backend, databases
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100