Work Mode
Work ≠ Chat. Chat is dialogue. Work is a durable goal → plan → steps → deliverable, with approvals for send/pay/delete and optional email/webhook intake.
Quick start
# Enable in config.yaml
# work:
# enabled: true
vibeos work doctor # gateway / IMAP / Computer Use blockers
vibeos work ready # one-shot: doctor + daemon + approvals + mail-rehearsal
vibeos work status
vibeos work create "Compare three tariffs into a one-page brief"
vibeos work create "Morning digest" --window morning # + day-part cron
vibeos work schedule --list
vibeos work connectors
vibeos work inbox
vibeos work show <wt_id>
vibeos work open # Desktop Work deep link (optional)
vibeos work complete <wt_id> # mark done from CLI
vibeos work approve <wt_id> # resume waiting_approval / quarantine
vibeos work approvals # list waiting + outbound asks
vibeos work outbound list # parked reply drafts
Desktop: switch to Chat | Work for inbox / task / live / approvals
(badge on Work when something waits).
TUI/CLI stay thin parity (vibeos work …, Telegram /work).
Operator readiness
vibeos work doctor # text
vibeos work doctor --json # exit 1 while blockers remain
Checks: work.enabled, gateway 24/7, IMAP/email_to_task, Computer Use TCC,
browser profile disk. If .env has a masked EMAIL_PASSWORD (***…), doctor
says so — paste a real app password, then vibeos work email-enable.
Always-on (24/7)
The gateway is the Work daemon — not Electron. See Work Mode 24/7.
vibeos work daemon status
Email → Work task
Only allowlisted senders become tasks. Empty allowlist + inbound on = refuse (never “execute all mail”).
Self-send dogfood: mail from your gateway EMAIL_ADDRESS to itself can
create a Work task (non-Re: subjects). Self-replies (Re: …) stay suppressed
so home-channel notify loops never open chat or spawn tasks. Chat turns are
never opened for self-mail.
work:
enabled: true
email_to_task: true
email:
inbound_to_task: true
sender_allowlist:
- you@example.com
- @trusted-client.org
injection_scan: true
approvals:
send: ask # outbound reply after done — ask by default
Suspicious bodies are quarantined (blocked WorkTask + ack), not silent tool policy. Noreply/newsletter senders are skipped.
Setup:
# Put real IMAP/SMTP secrets in ~/.vibeos/.env (EMAIL_ADDRESS, EMAIL_PASSWORD, …)
# or prompt interactively (password hidden):
vibeos work email-enable --interactive
vibeos gateway restart
vibeos work doctor # email_imap should be ok
Hermetic matrix (no live IMAP): vibeos work mail-rehearsal.
Connectors (MCP / skills — not core tools)
Work does not ship a ChatGPT-style Plugins directory or Salesforce-in-core. Use the MCP catalog and bundled skills:
| Need | Path |
|---|---|
| Calendar / Workspace | vibeos mcp install google-workspace or skill google-workspace |
| Drive files | vibeos mcp install google-drive (or Workspace when Calendar + Drive share OAuth) |
| Gmail API (optional) | vibeos mcp install google-gmail |
| CRM-ish boards | vibeos mcp install linear / notion; skill airtable for tables |
| Inbound mail → Work | vibeos work email-enable (real EMAIL_*) |
Agent playbook: skill work-connectors (related: work-operate).
Standalone vendor MCP/plugins belong in ~/.vibeos/plugins/, not in-tree
plugins/.
Webhook → Work task
Same pattern as kanban webhooks — set create_work: true on a route
(idempotent on delivery id). Existing create_kanban routes stay untouched.
Local dogfood without HTTP (same store path as the gateway handler):
vibeos work from-webhook "Nightly deploy note" \
--body "from CI" --delivery-id deploy-123
# same --delivery-id again → duplicate (no second task)
HTTP routes still require the platform HMAC (or shared secret) like other
webhooks — invalid signatures get 401. Hermetic coverage:
tests/gateway/test_webhook_create_work_hmac.py (valid / invalid / delivery-id
idempotent). Delivery-id retries return status: duplicate before a second
task is minted.
Browser profile & CAPTCHA
Work uses an isolated profile under $VIBEOS_HOME/browser-profiles/<name>
(work.browser_profile, default work). Do not point at personal Chrome
without explicit opt-in.
CAPTCHA default: autonomous solve + patience (work.challenge.*). Soft
challenges do not ping you on attempt 1. SMS/bank/photo-ID stay human-only.
Clearing a CAPTCHA is not permission to buy or send.
Offline smoke: scripts/smoke-work-browser.sh.
Approvals
| Action | Default |
|---|---|
| navigate / extract | allow |
| send / pay / delete / public share | ask |
Fleet + Work UI share one “waiting for you” list (command approvals, Kanban human rows, Work waiting_approval / quarantine, outbound email asks).
vibeos work approvals # unified inbox (CLI)
vibeos work outbound list # parked SMTP drafts only
vibeos work outbound approve <id> [--dry-run]
vibeos work outbound deny <id>
# Phone / Telegram:
# /work approvals
# /work outbound list|approve|deny …
Desktop: Chat|Work switcher shows a count badge when anything waits; task detail has Send reply / Deny send for outbound drafts; Fleet Control Approve/Deny for the same rows.
Outbound never silent-sends when work.approvals.send is ask (default).
Use --dry-run to clear a parked ask without SMTP.
Auto-review runs before Approve sends: floor rules always flag secret dumps
(sk-…, AWS keys, …). Broader wire/phishing phrases also ask when
work.approvals.send=ask or work.auto_review.enabled=true — still ask,
never silent block-send. Edit the draft or Deny.
Projects (memory)
Optional Work Project brief + findings shared across tasks (JSON under
$VIBEOS_HOME/work/projects/). Injected as user/context for later tasks —
never mid-run system-prompt rebuild.
Main brain + executor (optional)
Create Work can run in two modes (checkbox next to the brain model list):
| Mode | Checkbox | Brain list | Who runs |
|---|---|---|---|
| Standard | off | inactive (disabled) | Single executor model (or assignee profile default) |
| Dual | on | active — pick planner | Brain plans once via kanban_decompose; executor runs steps |
Defaults live under work.models in config.yaml (Settings → Chat shows the
same knobs). Per-task override is in the Create dialog.
work:
models:
dual_brain: false # checkbox default
executor_model: "" # empty → profile default
brain_model: "" # required only when dual_brain is true
Hermetic check (no live LLM): vibeos work models-rehearsal.
Anti-goals (honest)
- No second agent core / no mid-run toolset swap
- No
VIBEOS_WORK_*behavioral env vars — useconfig.yaml - Not a cloud Operator VM; sleep/power-off pauses Work
- Not a full ChatGPT Plugins directory clone
See also
- Work Mode 24/7
- ADR:
docs/plans/adr-work-mode.md - Phase notes:
docs/plans/2026-07-22-work-mode-phase-w*-progress.md