RFC: Import external agent sessions + hub-scoped operator context
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 5.1k
- Forks
- 570
- Avg merge
- 3d 11h
- Merged PRs (30d)
- 61
Description
Summary
HAPI works well when a session is born inside HAPI. It is awkward when work started in a native agent surface (Cursor IDE, Claude Code CLI, Codex CLI, etc.) needs to continue from the web/PWA or remote runner.
Today this is reported across several issues and partially addressed in draft work, but there is no single product/API story that covers: discover → import/attach → show scrollback → resume. This RFC proposes that story in small phases, including one architectural hook that keeps complex flows maintainable without one-off scripts per operator.
Problem
- Discovery gap – Native agent chats exist on disk (transcripts, session ids) but the web "new session" flow cannot list or attach them. Users must use CLI one-liners or custom scripts.
- Resume vs import –
POST /api/sessions/:id/resumereactivates an existing HAPI row. It does not import a chat HAPI has never seen. - Spawn gap – Runner/RPC already supports
resumeSessionIdfor several flavors, but the web spawn path has not consistently exposed it (see discussion on #572). - Scrollback gap – Even after attach, the web UI may show only post-attach traffic unless transcript/history is imported into the hub store (#268, #338).
Operators routinely hit: "I have an agent chat about project X; I want it in HAPI with history, from my phone."
Goals
- G1 – From the new-session UX, user can import an existing native chat or create new (clear fork in the flow).
- G2 – Machine-local discovery of importable chats (by agent flavor, directory, recency, title/preview).
- G3 – Import attaches native
resumeSessionId, preserves agent context, and backfills hub messages where feasible so the web thread is usable. - G4 – One extensibility point for flows that need reasoning/disambiguation (e.g. user describes a chat in prose instead of picking a row) without bolting logic into the web app.
Non-goals (this RFC)
- Replacing native agent session pickers inside Cursor/Claude/Codex UIs.
- Full-fidelity replay of every tool/sidechain event in imported transcripts.
- Requiring a separate hosted LLM product or API keys beyond agents the user already runs.
Related work
| Item | Notes |
|---|---|
| PR #518 | Draft: import existing Codex/Claude sessions, ImportExistingModal, import APIs, runtime config – strong overlap with G1–G3 for codex/claude |
| #572 | Cursor chats started outside HAPI – import/resume from web |
| #610 | Closed; maintainer bot noted missing web discover/import for native sessions |
| #268 | Codex pre-attach history missing in web |
| #338 | Resume/import history not visible after remote switch |
| #435 | Reuse local session (community ask) |
This RFC is meant to coordinate these threads, not duplicate them.
Proposal
Phase 1 – Web entry + spawn contract (smallest shippable)
- New-session screen: explicit Create new vs Import existing (not only an extra button buried in the form).
- Expose
resumeSessionIdonPOST /api/machines/:id/spawnend-to-end (schema, hub route, web client) for all supported flavors including Cursor. - Import path: user picks machine → directory → agent flavor → spawns with
resumeSessionId. - Document that agent brain continuity comes from native resume; hub row may start empty until traffic or Phase 2 backfill.
Acceptance: User imports a known Cursor/Codex/Claude id from web without CLI; session appears in list; agent answers "where did we leave off?" with native context.
Phase 2 – Discovery + scrollback
- Runner RPC + hub API, e.g.
GET /api/machines/:id/importable-sessions?directory=&agent=(name bikeshedding OK). - Returns:
externalSessionId,cwd,agent,previewTitle,previewPrompt,updatedAt,alreadyImported,importedHapiSessionId. - Security: same workspace-root rules as spawn/list-directory.
- Import action: spawn + transcript backfill into
messageswith correctinvoked_at(queued UI must not treat historical rows as pending user sends). - Extend discovery beyond codex/claude as flavors gain stable transcript layout (Cursor priority per #572).
Align implementation with PR #518 where it already exists; use this RFC as the checklist for Cursor + spawn wiring + backfill semantics.
Phase 3 – Hub-scoped operator context (architecture hook)
Some flows cannot be pure REST + forms:
- User describes a chat in prose ("issue with X in ~/coding/foo").
- Disambiguation among several matches in the same repo.
- Follow-up actions across multiple HAPI sessions (attach A, summarize B, open C).
Proposal: introduce a hub-scoped operator session (name bikeshedding: operator, control, meta):
- One long-lived session per machine/namespace (or explicit user action to open it).
- Agent flavor is user-selected (cursor, claude, codex, …) – same stack as project sessions, not a new model vendor.
- Tool surface is hub/runner RPCs (list importables, attach, list sessions, read session summary) rather than repo editing.
- Web/voice/CLI front ends call into this session when they need reasoning; deterministic UI continues to use Phase 1–2 APIs directly.
Import is the first consumer: NL-assisted attach is the proof this hook is needed. Later consumers (status triage, cross-session questions) reuse the same primitive instead of new one-off scripts.
This is intentionally narrow: the operator session is not a second product UI – it is the place HAPI invokes an agent above project sessions when the control plane itself needs a brain.
Suggested UX sketch (Phase 1–2)
[+] → Create new session | Import existing chat
|
+→ Import: Machine → Directory → Agent tabs
→ List (search/filter on title, path, id)
→ [Import] → open HAPI session
Optional later: "Describe the chat…" on Import screen → routes to operator session (Phase 3).
Open questions for maintainers
- Should import merge into an inactive HAPI row with history (reconnect) vs always spawn a new row when only native id is known?
- Preferred API shape: extend spawn vs dedicated
POST .../import? - Is PR #518 the implementation vehicle for Phase 2 codex/claude, with Phase 1/Cursor as follow-up commits?
- Naming/visibility for the Phase 3 operator session in the session list (pinned? hidden? separate nav?).
Why one RFC
Without a shared direction, we risk:
- Web spawn missing
resumeSessionIdwhile runner supports it. - Import UI for two flavors while Cursor (#572) stays manual.
- Transcript backfill fixed in one PR but regressions in queued-message semantics (#268/#338).
- Every advanced flow becoming operator bash (not maintainable for mobile users).
A phased RFC keeps Phase 1–2 mergeable independently while making Phase 3 explicit before ad-hoc NL features sprawl across web and voice.
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 with the POST /api/machines/:id/spawn path and its resumeSessionId handling, then review PR #518 and the related Cursor work in #572. The RFC spans phased web, runner, API, transcript, and operator-session changes; completion requires maintainers to choose the open API and architecture questions and meet the stated Phase 1–2 acceptance goals.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, backend, full-stack
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100