Owen is a decision engine that runs continuously and picks the highest-value next action. Here's how it works.
The Big Picture
┌─────────────────────────────────────────────────────────┐
│ External Services │
│ Gmail API │ GitHub API │ Jira API │ Google Calendar │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Owen Core │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Heartbeat │───▶│ Gather │───▶│ Decide │ │
│ │ (60s) │ │ State │ │ Engine │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Actions │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Local State │
│ tasks/ │ memory/ │ heartbeat-state │
└─────────────────────────────────────────────────────────┘
Component Breakdown
Heartbeat Loop
The main loop runs every 60 seconds (5 seconds in dev mode). It's deliberately simple:
while True:
state = gather_state()
action = decide(state)
execute(action)
sleep(interval)No event-driven complexity. No message queues. Just a loop.
State Gatherer
Collects context from everywhere:
- Gmail — unread count, important emails
- GitHub — PRs awaiting review, CI status
- Jira — tasks in each state
- Calendar — upcoming meetings
- Local tasks — files in tasks/open, tasks/doing, etc.
Outputs a unified state JSON that the decision engine consumes.
Decision Engine
A 14-rule priority ladder. First match wins:
- CI red / incident → Fix it
- Teammate blocked → Unblock them
- Active task → Continue it
- Meeting in 2h → Prep
- PR feedback → Address it
- Tasks in review → Review them
- PR review requested → Do it
- Email eligible → Triage
- Slack eligible → Check
- Open tasks → Pick one
- Uncommitted changes → Commit
- Generate tasks → Expand queue
- Surface debt → Flag tech debt
- Idle → Nothing to do
No AI in the decision layer. Pure if/else logic. Fast, predictable, debuggable.
Actions
Execute the decision:
- Gmail — archive, flag, draft responses
- GitHub — comment on PRs, approve/request changes
- Jira — transition states, add comments
- Local — move task files, update memory
Actions update state, which affects the next decision cycle.
Why This Works
Deterministic > smart. The decision engine doesn't try to be clever. It follows rules I can debug.
Local > cloud. Everything runs on my machine. No latency, no API limits, no privacy concerns.
Stateless decisions. Each heartbeat is independent. Crash recovery is trivial — just restart.
Observable. Every decision is logged. I can replay any cycle and understand exactly why it made that choice.
The Numbers
- 360 tests covering edge cases
- 8 packages (core, heartbeat, decision, owenai, actions, updater, service, dashboard)
- 7 integrations (Gmail, GitHub, Jira, Calendar, Slack, X, local tasks)
- 10 phases shipped over 4 days
The full source is at github.com/owendevereaux/owen.