Skip to main content

Projects and project tasks

Projects are daemon-owned coordination resources. They sit above sessions, runs, channels, and mailboxes without replacing any of them. Use them when you need durable work ownership, shared project membership, linked public channels, and project-scoped task tracking across multiple agent-backed sessions.

What a project is

A project is a top-level daemon record with:
  • a stable project_id
  • a display name and optional description
  • a lifecycle status
  • a durable member roster
  • zero or more linked channels
  • zero or more project tasks
  • caller metadata
A project is not:
  • a shared session
  • a shared run queue
  • a second public messaging system
The execution model stays the same:
  • sessions still execute work
  • runs still represent concrete execution
  • channels still hold public conversation
  • mailboxes still carry private inter-agent coordination

Projects versus session tasks

Kheish now has two different task concepts:
  • session tasks are session-scoped control records used inside the execution model
  • project tasks are daemon-owned work items attached to a project
Session tasks are covered in Tasks and schedules. Project tasks are durable coordination records that can point at:
  • one assignee project member
  • one assignee session
  • one latest associated run
  • one optional public discussion thread
  • other project tasks through blocked_by
Do not treat project tasks as a rename of the older session task model.

Choosing the right primitive

Use only sessions and runs when:
  • one execution context can own the work directly
  • you do not need durable cross-session ownership or coordination
Use channels when:
  • the shared state is mainly a public conversation
Use projects when:
  • multiple sessions need durable shared membership
  • work ownership or dependencies must outlive one run
  • public channel discussion should stay linked to explicit task records

Members

Project members support the same member kinds used by channels:
  • human_actor
  • session
Important current rules:
  • only session members can own project tasks
  • the same session cannot be registered twice in one project under two different member ids
  • assignment can be resolved by project member_id, session_id, or live agent_id
This lets one project carry both operator identities and agent-backed sessions while keeping assignment and execution pinned to real daemon sessions.

Linked channels

Projects can link existing daemon-owned channels. Each link currently stores:
  • the linked channel_id
  • an optional semantic role
  • default_for_new_tasks
  • mirror_members
  • caller metadata
default_for_new_tasks means:
  • if a project task has no explicit discussion thread and the daemon needs to create one at start time, it uses that linked channel
mirror_members means:
  • project members are mirrored into the linked channel as normal channel members
Current mirrored member ids are namespaced inside the channel:
  • project:{project_id}:{member_id}
That prevents collisions with unrelated channel members that might already use the same local member_id.

Project tasks

Project tasks are daemon-owned records with:
  • project_task_id
  • title and description
  • status
  • optional assignee member id
  • optional assignee session id
  • optional latest associated run id
  • optional discussion reference
  • dependency ids in blocked_by
  • optional output
  • metadata and timestamps
Current statuses reuse the shared daemon task status family:
  • pending
  • in_progress
  • blocked
  • completed
  • failed
  • cancelled

Task discussion threads

Project tasks can point at one public thread through:
  • discussion.channel_id
  • discussion.thread_root_message_id
If a task already points at a linked channel thread and that thread still exists, the daemon reuses it. If no discussion is set and the project has one linked channel with default_for_new_tasks=true, the daemon can create a kickoff thread there when the task starts. That kickoff thread is posted by a synthetic human actor:
  • project-control
The thread is public project coordination state. Execution still happens in the assignee session through a normal run.

Starting a project task

POST /v1/projects/{project_id}/tasks/{task_id}/start starts work by creating a normal daemon run in the assigned member session. Current start rules are strict:
  • the project must be active
  • the task must be assigned
  • the assignee must be a session-backed project member
  • all declared dependencies must already be completed
  • terminal tasks must be reopened before start
  • a second start is rejected while the latest associated run is still non-terminal
When start succeeds, the daemon:
  1. reuses the current public discussion thread when it is still valid, or creates one if the project has a default linked channel
  2. otherwise, it can continue without any public discussion thread
  3. submits a normal input run in the assignee session
  4. stores the new latest_run_id
  5. keeps primary_session_id aligned with the assignee session
Project-task status after start is derived from the run state:
  • queued run -> project task stays pending
  • every other current run state -> project task becomes in_progress

Dependency validation

Project-task dependencies are validated when they are created or replaced. Current validation rejects:
  • missing dependency ids
  • self-dependency
  • cycles
Duplicate dependency ids are normalized away rather than treated as an error. The daemon also blocks task start until every dependency is completed.

Lifecycle guards

Projects participate in daemon topology rules. Current guards include:
  • a channel cannot be deleted while any project still links it
  • a project channel link cannot be removed while non-terminal tasks still reference that channel as their discussion channel
  • a session cannot be ended while it is still a project member
  • a session also cannot be ended while it still owns non-terminal project tasks
These guards exist so daemon-owned project state does not silently point at missing channels or dead sessions.

Persistence and recovery

Projects and project tasks are persisted under the daemon state root as daemon-owned records, separate from session journals and separate from channel logs. That means:
  • projects survive daemon restart
  • project tasks survive daemon restart
  • project-task discussion references and latest run ids survive restart
Mirrored channel membership is persisted through the normal project and channel stores. Later project mutation and project-task start paths reconcile the mirrored roster against the current persisted project state.

When to use projects

Use projects when you need:
  • one durable work area spanning multiple sessions
  • named members and explicit ownership
  • linked public coordination channels
  • operator-visible work decomposition that outlives one run
Use only sessions and runs when you just need execution without durable project coordination.