Create and execute a Mission

Goal: run the full product lifecycle with today’s APIs.

Mission  →  Execution  →  Thread  →  Run(s)  →  result

Vocabulary

  • Mission — reusable objective (name + prompt). Not a Celery task.

  • Execution — one concrete business request (user + agent + mission).

  • Thread — persistent timeline / LangGraph thread_id.

  • Run — one technical attempt to advance that Thread.

Create a Mission

REST:

POST /api/mission/
Content-Type: application/json

{
  "name": "Daily briefing",
  "prompt": "Summarize what you know in three bullet points."
}

Python:

from agency.models import Mission
mission = Mission.objects.create(
    name="Daily briefing",
    prompt="Summarize what you know in three bullet points.",
)

Associate an Agent

Missions are not permanently bound to one Agent. You pick the Agent at dispatch time (agent_id).

Dispatch (current mechanism)

Authenticated POST:

POST /api/mission/<mission_uuid>/dispatch/
Content-Type: application/json

{"agent_id": "<agent_uuid>"}

Omit agent_id to use the signed-in user’s active agent (UserPreferences.active_agent; Veronica when unset).

What happens today (mission_dispatch → Mission.dispatch → start_mission):

  1. Create Execution (status starting) and Thread (title = mission name).

  2. Enqueue Celery agency.start_mission with mission name, agent id, user id, execution id.

  3. Worker calls Agent.execute(..., execution=execution), which reuses that pair and runs ThreadRunner.run.

  4. Response returns immediately:

    {
      "execution_id": "...",
      "thread_id": "...",
      "task_id": "...",
      "mission_name": "...",
      "agent_name": "..."
    }
    

Celery task_id is transport only. Domain status lives on Execution / Run rows.

Locate Execution, Thread, Runs

There is no public /api/thread/ or /api/run/.

Inspect via Execution detail:

GET /api/execution/<execution_uuid>/

Useful fields on the detail serializer:

  • status, result, metadata

  • thread_id — first thread

  • threads — nested threads with runs/checkpoints (as implemented)

  • interruptions, messages, result_messages

Django admin also exposes Thread / Run / Checkpoint.

Obtain the result

When the run finishes without HITL, Agent.execute stores a serializable graph output on execution.result and sets status success (or interrupted if __interrupt__ is present).

Poll:

GET /api/execution/<execution_uuid>/

Or watch Mission Control (REST hydrate + Channels projection).

ASCII lifecycle

Mission "Daily briefing"
     │
     │  POST .../dispatch/  {agent_id}
     ▼
Execution  (business intent)
     │
     └── Thread  (timeline / thread_id)
              │
              └── Run #1  (technical attempt)
                       │
                       ├─ SUCCESS  → execution.result
                       ├─ ERROR
                       └─ INTERRUPTED → see HITL tutorial

Next: Example missions (boot seed) · Human-in-the-Loop · Processes: Execution Runtime. Mission Control (Agents / Missions / Executions app): Mission Control.