Runs work on a task or in a conversation
People want to talk to a role directly, outside any task, and later reach it from elsewhere, such as Slack: one ongoing conversation per person and role, whose agent keeps a directory of its own and is woken when tasks it watches change. Runs were tied to tasks throughout, and the run manager did two jobs at once: deciding which role should work on which task, and hosting agent processes. We decided that a run works on a task or in a conversation, and split the run manager along that line: a host owns agent processes (slots, sessions, idle sleep, prompts, transcripts, failures) and decides when a run is prompted; a driver for each kind of run decides whether it should run, where it works, what it is told, and what becomes of the end of a turn. A conversation has a single run, which lasts as long as the conversation does. Whatever should reach a run only nudges it, and its driver reads what is new since the run last looked from the database, so news survives a restart although events are in-process (ADR 0003).
Considered Options
- A conversation as a special task: rejected; it would sit in lists and boards in progress forever, muddle triage and review, and could not hold to one per person and role. It would have been the quickest prototype, as tasks without a project already have a directory, comments and waiting runs.
- A conversation manager of its own: rejected; it would duplicate the run lifecycle, and the slots for agent processes must be shared anyway.
- Binding the task or conversation into the run's token: rejected; the token names the run alone, and what it may do is worked out from the run on the server. That is checked on every call, so a person who leaves loses access at once rather than when a token expires, and the token stays opaque for runtimes started in a sandbox (ADR 0004).
- Limiting a conversation's agent to what both its role and its person may do: rejected; any member can already give any role a task, so a conversation reaches nothing a task does not. Its agent acts with its role's access, as on a task without a project.
Consequences
- Comments reach a task's agent the same way as everything else: as news read since it last looked, not handed to it.
- An agent's changes record the run that made them, so a conversation is not woken by what its own agent did, but is when the same role changes the task from a run on that task.
- A conversation's agent has the tools of a task without a project, with no task of its own: task tools name their task, it creates tasks rather than subtasks or proposals (ADR 0012), and it can send a message, subscribe and unsubscribe.
- A turn that began with a person's message always ends in a reply to them. A turn woken only by tasks it subscribes to says nothing unless the agent sends a message, so the person hears what needs them, not every comment.
- A conversation's session keeps growing. A person can start fresh: a new session in the same conversation, with the same messages, directory and subscriptions; its opening prompt carries the recent messages and the subscribed tasks. The messages said before are archived: the agent reads them as before, but the person sees them only when they ask to.
- Messages are published as events once committed, as task changes are. The conversation's run and the web UI listen to them; another channel, such as Slack, would be one more listener, sending people's messages in the same way the web UI does.