Skip to content

Orchestration

Architecture & Code

Orchestration

The multi-agent orchestration layer — companies, agents, wakeups, runs, live events — and the operational sequences that move work through it.

The multi-agent orchestration layer and the sequences that move work through it. Use the Full screen button above, or open the orchestration diagram in a new tab ↗.

Company Orchestration System

The company system is the multi-agent orchestration layer. It owns companies, agents, projects, goals, issues, routines, activity, runs, approvals, and company-scoped files.

Core Domain Objects

ObjectPurpose
CompanyTenant boundary for agents, issues, projects, secrets, channels, and files
AgentCompany teammate with role, adapter config, runtime config, instructions, skills, and env
ProjectWorkspace and project-scoped configuration for issues and files
GoalHigh-level objective that can group issues and routines
IssueUnit of company work assigned to an agent or moved through lifecycle states
RoutineScheduled or trigger-based recurring work owned by an agent
Wakeup requestDurable queue item that tells an agent why it should run
Heartbeat runExecution record for one agent invocation
Activity logAudit/event history for user, agent, and system actions
Company secretCompany-scoped secret reference used by env bindings

Wake Sources

An agent run can be started from several sources:

  • Issue assigned to an agent.
  • Issue comment or mention.
  • Approval stage or review decision.
  • User clicks run heartbeat.
  • Background heartbeat timer fires.
  • Routine timer fires.
  • Channel inbound message is routed to the agent.
  • Direct company-agent chat message is sent.

All of these are normalized into wake context before execution. The agent should not need to know whether the wake came from the UI, a timer, an issue, or a channel except through the wake fields it receives.

Wakeup Queue Flow

apps/api/src/orchestration/engine/wakeup.ts owns the durable queue helpers.

Work source
enqueueWakeup(agentId, source, reason, payload, contextSnapshot)
agentWakeupRequest status queued
scheduler or immediate runner claims wakeup
heartbeat_runs row is created or updated
agent-invoker starts runtime process
wakeup completed or failed

The wakeup record captures:

  • agentId
  • source
  • triggerDetail
  • reason
  • payload
  • contextSnapshot
  • queue status and timestamps

The context snapshot is important because it is the stable handoff from product events to runtime execution. For example, an issue assignment wakeup includes the issue id and source context even if the issue later changes.

Run Lifecycle

Run status is not the same as agent status.

queued -> running -> succeeded | failed | cancelled

Run status describes one execution attempt. Agent status describes the visible state of the agent. A queued run should not overwrite an already-running agent as if the agent itself stopped running. The UI and event consumers should treat run lifecycle events and agent lifecycle events as separate streams.

Agent Status

Agent status should be updated only when the agent state actually changes, for example:

  • idle
  • active
  • running
  • paused
  • error

Queued work is a run property. It may be displayed near the agent, but it should not be treated as the agent’s primary lifecycle unless the backend deliberately sets an agent status event.

Live Event Bus

apps/api/src/orchestration/engine/event-bus.ts publishes company live events. The shared types live in packages/shared/src/orchestration/types/live.ts, and event names live in packages/shared/src/orchestration/constants.ts.

Important event families:

Event familyPurpose
heartbeat.run.queuedA run exists and is waiting or starting
heartbeat.run.runningA run has started
heartbeat.run.logRuntime SDK stream event, tool event, text, thinking, or system event
heartbeat.run.completedRun completed successfully
heartbeat.run.failedRun failed
heartbeat.run.cancelledRun was cancelled
agent.statusAgent state changed
issue.createdAgent or user created an issue
issue.updatedIssue fields changed, including status or assignee
issue.comment.createdComment was written
issue.deletedIssue was soft or hard deleted
activity.loggedAudit log entry was created

Live event payloads should include enough denormalized data for subscribers to update without refetching the entire company:

  • run id, run status, session id, adapter type, timestamps
  • agent id, agent name, role, status, adapter/runtime metadata
  • issue id, identifier, title, status, assignee, project, goal
  • activity actor, action, entity, details

Refetching is still acceptable for recovery, but the normal path should consume the event payload directly.

Activity Log

Activity logs are audit records, not only UI feed items. They preserve:

  • company id
  • actor type
  • actor id
  • agent id
  • run id
  • action
  • entity type
  • entity id
  • details

They are used to reconstruct what happened around an issue, run, routine, or agent action even after live events are gone from memory.

Operational Sequences

Issue Assignment

User or agent creates/updates issue with assignee
issue service persists issue
activity.logged is emitted
queueIssueAssignmentWakeup enqueues wakeup
scheduler claims wakeup
heartbeat run is queued
heartbeat.run.queued event
agent-invoker starts runtime
heartbeat.run.running event
runtime reads task/inbox via run-token APIs
runtime comments, updates issue, writes files, or asks for approval
issue/activity/run live events stream to subscribers
heartbeat.run.completed or heartbeat.run.failed

Direct Company-Agent Chat

User selects company agent
direct chat session is resolved or created
selected runtime/model comes from agent configuration
message is sent through runtime adapter
response streams back to the chat panel
session id is remembered for that agent

Direct chat does not have to create a company issue. It can still use company context, agent instructions, skills, files, env, and channel tools.

Heartbeat Timer

Heartbeat scheduler tick
reads agents with runtime_config.heartbeat.enabled
checks interval and active run policy
enqueueWakeup(source=“timer”, reason=“heartbeat_timer”)
run starts with no issue id
agent inspects inbox-lite or heartbeat instructions
agent exits if no work is needed

Turning heartbeat on in the agent configuration updates scheduler input. The next scheduler tick should observe the new runtime config without requiring the agent process to stay alive.

Routine Timer

Routine scheduler tick
finds active routine triggers by nextFireAt
creates routine wake context
starts or queues agent run according to routine policy
updates nextFireAt in UTC
displays next run in the user’s/browser timezone

UTC is the storage format. The routine timezone controls when the schedule fires. Browser timezone can be used as a default when the user or agent did not specify a timezone.

Channel Inbound Message

External channel message
transport plugin verifies and parses message
channel session maps to company/agent/session
dispatch builds runtime context
runtime answers
stream sink sends or edits outbound response
channel session and audit state update