Enrichment Features
End-user-facing capabilities layered on top of the agent runtime. Each ships as a tool/service + REST route + web page.
Reader
Section titled “Reader”Fetch a URL, extract the readable content, and run reader actions on it.
- Code:
src/core/reader/(fetch.ts,extract.ts,actions.ts) - Route:
src/api/routes/reader.ts - Web:
web/app/reader/page.tsx
The fetcher is SSRF-guarded. Extraction strips boilerplate to readable text.
Deep Research
Section titled “Deep Research”Bounded, multi-source investigation that produces a cited report.
- Code:
src/core/research/(jobs.ts,gather.ts,synthesis.ts,render.ts,persist.ts,service.ts) - Route:
src/api/routes/research.ts - Web:
web/app/research/page.tsx
Flow: plan queries → gather sources (SSRF-guarded fetch) → synthesize a sectioned,
cited report → render. Depth (quick / standard / deep) bounds fan-out width
and source count (DEPTH_BUDGET).
The web page keeps the investigation ID in /research?job=<id>. Opening that
address again checks the existing job rather than starting another one. The Work
navigation remembers this address while you move between pages in the current app
session; bookmark it to return after closing the app. Missing or inaccessible jobs
stop polling and offer an explicit status retry. Investigations are personal to
the signed-in user, including when a shared workspace is selected. For research
visible to teammates as it happens, ask your companion in a shared room.
On completion, Octipus attempts to save the Markdown report as a Documents
record (category Research) and index it into the knowledge base. Indexing is
fail-soft: if embeddings are unavailable, the document can still be saved and the
reason is logged. Document persistence can also fail; the completed job can carry
the report without a document link. Check documentId before treating it as a
saved document.
Job tracking is stored in background_jobs. The job record survives a restart;
the running computation does not resume automatically. The boot recovery sweep
marks abandoned work as interrupted, exposed by the research polling API as
error with a reason. Saved documents and any successfully created follow-up
to-do remain durable. See src/core/research/jobs.ts and
src/core/jobs/recover.ts.
To-Do List
Section titled “To-Do List”The user’s personal to-do list. Agents can add, update, and complete items.
- Tool:
src/tools/tasks/(TasksTool, displayed as To-Do List; tool id staystasks, route/tasks) - Route:
src/api/routes/tasks.ts, recurring items viaroutes/recurring-tasks.ts- the scheduler
- Web:
web/app/tasks/page.tsx(sidebar entry to-do)
Distinct from src/tools/task-state/ — a read-only inter-agent/workflow state tool
that shares neither storage nor concept.
What next. GET /api/tasks?view=next (and list_tasks with view: "next")
returns open tasks in next-action order — overdue → due today → high priority →
new from email / research / reading in the last 48h → due this week → backlog —
each with a bucket and a one-line reason. “Today” is the user’s calendar
day: the page passes the browser’s zone as ?tz=, the tool uses the user’s
saved timezone preference, and both fall back to UTC — never the server’s
zone. The ranking is one pure function (src/core/tasks/rank.ts) shared by
the tool, the API and the tasks page’s what next grouping (the default); the
Daily Briefing asks the tool for this view rather than re-sorting.
Provenance. Every task carries source (user | agent | reader | research | email) and a sourceRef linking back to where it came from. The producers live
in src/core/tasks/sourced.ts:
| Source | How a task gets created |
|---|---|
reader | save as to-dos on a Reader Action items result (POST /api/reader/tasks) — one task per bullet, linked to the article URL, category Reading. |
email | To-do on an open message (POST /api/email/message/:id/task) — subject as title, sender + snippet in notes, triage priority mapped onto task priority, category Email. The email-processor tool also tells the agent to create_task for mail that needs the user. |
research | Automatic on every finished Deep Research run — one Review research: … task pointing at the saved document (sourceRef.documentId), category Research. |
While you were away
Section titled “While you were away”One list of what happened to the user’s work since they last looked: agents that finished or failed, pipelines that completed or now wait on them, approvals blocking a run, to-dos other things created for them, and the unread notifications that arrived in the window (older unread mail is the inbox’s business, so “nothing happened” stays reachable). A pipeline that is still running is not news yet and is left out. Approvals and failures come first — they are the only items where nothing moves until the user acts.
- Core:
src/core/digest/away.ts—collectAwayDigestfoldsagents,pipelines,tasks,notificationsand the in-process approval list;renderAwayDigestis the deterministic markdown of the same facts. - Route:
GET /api/digest/away?since=<iso>(default: 24h; clamped to 30d). - Web: the first card on the dashboard (
web/components/dashboard/away-digest.tsx). caught up remembers the moment in the browser and starts the next “away” there. - Briefing: a
spawn_agenthook withactionConfig.awayDigestHoursgets the rendered digest prepended to its prompt — the seeded Daily Briefing uses 24 — so the agent reads facts instead of spending a turn collecting them.
Inbox (notifications)
Section titled “Inbox (notifications)”Every notification the platform raises for a user — an agent finished or
failed, a pipeline completed, stopped or errored, an approval is waiting — lands
in the notifications table and in the header bell. The inbox page is the
full view of the same rows: filter by unread / agents / pipelines / approvals,
mark one or all read, and follow each row to the thing that happened (the
agent view, the pipelines page, the chat that is waiting for the approval).
- Routes:
src/api/routes/notifications.ts(GET /api/notificationswith?unread=1,?type=<prefix>,limit,offset— filters apply in SQL so paging is over the filtered set;POST /api/notifications/:id/read,POST /api/notifications/read-all) - Web:
web/app/notifications/page.tsx(sidebar entry inbox) - Producers:
worker-spawner.ts,pipeline-manager.ts,approval-manager.tsviagetNotificationService().notify(...); themetadatathey attach (workerId,pipelineId,requestId) is what the inbox links on.
Email triage
Section titled “Email triage”Batch, per-email AI classification and actions over Gmail / Microsoft 365.
- Tool:
src/tools/email-processor/(EmailProcessorTool) - Core:
src/core/email/(send/normalize) - Route:
src/api/routes/email.ts(send is gated) - Web:
web/app/email/page.tsx
Hardware-aware onboarding (hwfit)
Section titled “Hardware-aware onboarding (hwfit)”Recommends local Ollama models that fit the host’s hardware.
- Code:
src/capabilities/hwfit/(catalog.json/catalog.tscurated catalog,scorer.ts,sizing.tsLIVE registry manifest sizing,install.ts) - Driver:
src/capabilities/service.ts - Route:
src/api/routes/capabilities.ts - Web:
web/app/setup/page.tsx
Combines a curated model catalog with live registry manifest sizing and a hardware budget score to surface installable models the machine can actually run.