Multi-App Coordination
Overview
Section titled “Overview”Single-capability invocations handle one action in one application. Real workflows span multiple applications and multiple steps. PCP provides a coordination layer that composes individual capability invocations into structured multi-app workflows with defined failure handling and rollback semantics.
The coordinator runs inside the System Intelligence layer. It receives a coordination plan from SI, dispatches individual capability invocations to the compositor in the specified order, and aggregates results or handles failures according to the plan’s strategy.
Coordination Primitives
Section titled “Coordination Primitives”PCP supports three coordination primitives that cover the common patterns of multi-app workflows.
Sequence
Section titled “Sequence”Actions execute in order. If any step fails, the sequence stops immediately. This is a fail-fast model: no subsequent steps run after a failure.
Consider a workflow that reads an email, extracts a meeting time, creates a calendar event, and sends a confirmation. If the calendar creation step fails, the sequence stops right there. No confirmation message is sent, because the precondition for that confirmation (a successful calendar event) was never met.
The sequence primitive guarantees that later steps never observe a state where an earlier step has failed. Each step can trust that all prior steps completed successfully.
Parallel
Section titled “Parallel”Multiple actions execute concurrently. The coordinator waits for all to complete before returning. Results from each action are gathered into a single response object, keyed by action identifier.
A search workflow provides a good example: searching mail, checking the calendar, and looking up a contact can all run at the same time. None of these actions depends on the result of another, so parallel execution reduces total latency. The caller receives all three results together once every action finishes.
Parallel execution does not imply any ordering between the concurrent actions. Two parallel file writes to the same path will race, and the coordinator does not arbitrate that conflict. The caller is responsible for ensuring that parallel actions do not have conflicting side effects.
Conditional
Section titled “Conditional”A conditional dispatches actions based on the result of a previous step. The coordinator evaluates a condition against the output of a completed step, then routes to one of two or more branches.
For example: if an email contains an attachment, save it to disk and notify the user. Otherwise, just read the body text and summarize it. The condition checks a property of the email payload (presence of an attachment), and the coordinator dispatches the appropriate branch without involving the caller in a second round trip.
Conditionals can nest. A conditional branch can itself contain a sequence, a parallel group, or another conditional. This nesting allows the coordinator to express complex decision trees without requiring SI to issue multiple serial requests.
Coordination API
Section titled “Coordination API”The coordinator exposes two primary methods corresponding to the sequence and parallel primitives. Conditionals are expressed through the Coordinate::when variant, which wraps a condition expression and two or more branch plans.
// Sequence: fail-fastlet result = coordinator.sequence(vec![ Coordinate::invoke("mail.read", params), Coordinate::invoke("calendar.create", params), Coordinate::invoke("comm.send_message", params),]).await;
// Parallel: gather-alllet results = coordinator.parallel(vec![ Coordinate::invoke("mail.search", params1), Coordinate::invoke("calendar.list_events", params2), Coordinate::invoke("files.search", params3),]).await;
// Conditional: branch on resultlet result = coordinator.sequence(vec![ Coordinate::invoke("mail.read", params), Coordinate::when( Condition::field_exists("attachments"), vec![Coordinate::invoke("file.save", save_params)], vec![Coordinate::invoke("text.get", body_params)], ),]).await;Each Coordinate::invoke carries a capability ID and its parameters. The coordinator resolves the target application from the capability ID and dispatches through the compositor’s normal capability routing. The coordination layer adds no new capability types; it composes existing ones.
Transaction Model
Section titled “Transaction Model”Multi-step workflows run inside a transaction. The transaction model provides a consistent framework for timeout handling, failure recovery, and audit correlation.
Transaction Strategies
Section titled “Transaction Strategies”PCP offers two strategies that control what happens when a step fails.
ATOMIC means all steps must succeed. If any step fails, the coordinator triggers defined rollback actions to revert the state changes made by prior steps. The transaction either fully completes or fully rolls back. There is no partial completion state visible to the caller.
A file move provides a concrete example. The implementation is a copy followed by a delete: copy the file from A to B, then delete the original at A. If the copy succeeds but the delete fails, the file system now has two copies. The ATOMIC strategy’s rollback action deletes the copy at B, restoring the original single-copy state.
BEST_EFFORT means steps execute sequentially, and if a step fails, the transaction records the failure and continues with the remaining steps. No rollback occurs. The caller receives a result object that lists which steps succeeded and which failed.
A cleanup workflow demonstrates the fit. Closing all non-essential applications before a system update does not require all closures to succeed. If one application refuses to close, the transaction continues closing the others. The caller can inspect the result to see which closures failed and decide whether to retry or force-close.
Transaction Properties
Section titled “Transaction Properties”Every transaction carries four properties:
A transaction ID (UUID) that ties together all log entries, capability invocations, and rollback actions from a single coordination plan. Audit trails use this ID to reconstruct the full lifecycle of a multi-step operation.
A timeout that caps the total execution time. The default is 30 seconds. Callers can override this per transaction. When the timeout fires, all pending steps are cancelled immediately.
Per-step timeout budgets that the coordinator enforces within the overall transaction timeout. If a transaction has a 30-second total timeout and five steps, the coordinator can allocate 5 seconds per step, or assign uneven budgets (10 seconds for a network call, 2 seconds for a local file operation). Step timeouts are optional; without explicit budgets, steps run until the transaction-level timeout fires.
Rollback actions (ATOMIC strategy only) that define how to undo each step. Rollback actions execute in reverse order of the original steps. If steps A, B, and C executed in that order and step C fails, the coordinator runs rollback for B, then rollback for A.
Error Handling
Section titled “Error Handling”Four error conditions occur within coordinated transactions.
Transaction timeout fires when the total elapsed time exceeds the configured timeout. All pending steps are cancelled. Under the ATOMIC strategy, the coordinator initiates rollback for all completed steps. Under the BEST_EFFORT strategy, the coordinator records the timeout as a failure for each pending step and returns partial results for the completed steps.
Step failure occurs when an individual capability invocation returns an error. Under ATOMIC, the coordinator stops the sequence and begins rollback. Under BEST_EFFORT, the coordinator records the failure and proceeds to the next step.
Ambiguous target occurs when the coordinator cannot resolve a capability ID to a single application or surface. This is a planning-time failure, not a runtime failure. The transaction fails immediately with an AMBIGUOUS_TARGET error before any steps execute. No rollback is needed because no state changes occurred.
App unresponsive occurs when a target application does not respond to a capability invocation within its step timeout. The coordinator treats this as a step failure and applies the strategy’s failure handling. The compositor marks the application as unresponsive, which may trigger escalation (notification to the user, retry with elevated privileges, or forced termination depending on configuration).