Skip to content

Goals & Reflection ​

Uranus agents are designed to operate autonomously over long horizons. Two primitives close the loop between what an agent is trying to do and what it actually did: goals and reflections.

Why this exists ​

A pure chat-driven agent forgets why it acted as soon as a conversation ends. With goals declared and a periodic self-review running, the agent can:

  • Stay aligned with declared objectives across conversations and gateways
  • Notice patterns in its own behaviour (failed workflows, recurring requests)
  • Update its plan without a human re-prompting it every turn
  • Propose new automations (draft workflows) when something looks worth automating

Goals ​

A goal is a durable objective the agent persists across sessions. Goals live in the agent_goals table and are loaded into the system prompt every turn.

Fields ​

ColumnPurpose
descriptionWhat the agent is pursuing (1–2 sentences)
statusactive · paused · completed · abandoned
priority1 (low) – 10 (high), default 5
target_dateOptional ISO date for soft deadline
progress_notesAccumulating log of what's been done; appended by workflows and reflections
parent_goal_idOptional hierarchy for sub-goals
sourceuser · reflection · workflow · system

LLM tools ​

ToolEffect
set_goal(description, priority?, target_date?, parent_goal_id?, workflow_ids?)Declare a new goal. Pass workflow_ids to pre-link workflows that pursue it.
update_goal(goal_id, status?, progress?, priority?)Revise a goal.
list_goals(status?)Read goals. Returns linked workflows in the same row.

Workflow linkage ​

When a workflow runs successfully and was invoked with execute_workflow(workflowId, ..., goal_id=...), the goal's progress_notes get a new line:

[2026-05-15] Daily standup: completed

The goal_workflows(goal_id, workflow_id, role, weight) table holds the many-to-many. role is one of achieves (completes the goal), advances (pushes forward), or evaluates (checks status).

Reflections ​

A reflection is a structured self-review that the agent runs against its own recent activity. The output is a row in agent_reflections:

ColumnPurpose
period_start, period_endWindow the reflection covered
triggerscheduled · manual · error_spike · goal_deadline
observationsWhat actually happened (3–5 sentences)
learningsBullet list — what to do differently
planSpecific actions for the next period
goal_updatesJSON: which goals were advanced/paused/completed
metricsJSON snapshot: tool calls, errors, messages, money flow, schedules
model_idWhich LLM produced the reflection

When reflections run ​

  • Daily cron at 03:00 UTC, auto-seeded on first agent wake (callback: "reflection:24h")
  • Manual via reflect_now(period?) tool — useful when something just changed materially
  • Error spike when more than 5 workflow failures land in a 10-minute window (throttled to once per 30 minutes)

Inputs the reflection LLM sees ​

For the chosen time window, gatherSignals pulls in parallel:

  • Currently active goals (top 10 by priority)
  • Message counts split by role
  • Tool call breakdown (via json_each on chat_messages.metadata.toolCalls)
  • Recent error log entries from agent_logs
  • Workflow execution status counts and per-workflow rollup (W6)
  • Schedule fire counts
  • Money flow (in/out USD from transactions)
  • Top active contacts
  • Recent conversation summaries
  • The previous reflection's plan (for continuity)

Output structure ​

The reflection LLM returns JSON:

json
{
  "observations": "...",
  "learnings": "...",
  "plan": "...",
  "goal_updates": [
    {"goal_id": "...", "status": "completed", "progress": "shipped"}
  ],
  "new_goals": [
    {"description": "Audit weekly invoices", "priority": 6}
  ],
  "reflective_memories": [
    {"topic": "user-prefers-tldr", "fact": "User explicitly asked for shorter answers"}
  ],
  "proposed_workflows": [
    {
      "description": "Auto-tag incoming receipts",
      "trigger_kind": "gateway_event",
      "outline": "Step 1: detect attachment...\nStep 2: ..."
    }
  ]
}

Side effects of applyReflection ​

Output fieldWhere it lands
observations / learnings / planagent_reflections row
goal_updatesagent_goals rows updated (status / progress_notes)
new_goalsagent_goals rows inserted with source='reflection'
reflective_memoriesmemory:reflection:{date}:{topic} keys in agent_state + embedded into Vectorize at confidence 0.85
proposed_workflowsworkflows rows inserted with status='draft' source='reflection' (never auto-activated)

Re-injection into the next turn ​

The system prompt loader (buildEnhancedSystemPrompt) reads the most recent reflection (within 7 days) and surfaces its plan + learnings as a dedicated section:

## Recent Self-Reflection (2026-05-15T03:00:00Z)
**Plan from last reflection:** Focus on...
**Recent learnings:** ...

This closes the loop — reflections don't get written to a black hole; they shape behaviour on the next turn.

Draft workflows ​

Workflows proposed by reflection are inserted with status='draft' and source='reflection'. They appear in the existing Workflows UI tab (filterable by status). The agent can list and approve them via two LLM tools:

ToolEffect
list_draft_workflows()Returns drafts pending review
activate_draft_workflow(workflow_id)Flips draft → active. Requires user approval (in TOOLS_REQUIRING_APPROVAL). Mints the workflow's callback secret + embeds it for semantic discovery.

Cost ​

Reflection runs use @cf/zai-org/glm-4.7-flash with a fallback to Llama 4 Scout. At Cloudflare Workers AI rates (verified 2026-05-15):

  • glm-4.7-flash: $0.06 / 1M input, $0.40 / 1M output tokens
  • A daily reflection ≈ 2K input tokens + 500 output tokens ≈ $0.0003/day per agent

Schema ​

See migrations:

  • 058_agent_goals.sql
  • 059_agent_reflections.sql
  • Agent Memory — where reflective memories live and how they're recalled
  • Workflows — goal-workflow linkage and draft workflows in detail
  • Scheduling — the daily reflection cron and other auto-seeded jobs