Skip to content

Composable applications ​

Architecture requirement, recorded 16 October 2026. OpenAgent must support composing persistent, interactive applications from independently supplied tools, data sources and UI components. Multiple accounts of one provider and multiple providers must be usable in the same application. This document defines the extension boundaries and acceptance criteria; it does not announce a shipped application framework or implement the reference applications.

The reference cases are a calendar over several accounts, a task tracking system, and document management over several filesystems with editing. They test the architecture's generality. Their provider tools and domain behavior remain independent integrations; none is required by Core or added by this decision.

Composition and ownership ​

An application assembles a versioned definition, data bindings, actions, views and lifecycle policy. It can be created by a developer or an authorized agent. Its ordinary interactions must execute deterministically without requiring a model turn for every click, keystroke, refresh or synchronization step. Agent reasoning remains available when the interaction calls for it.

LayerResponsibilityBoundary
CoreVerified execution context, authorization, capability discovery and dispatch, durable runs and optional modulesPublic contracts; no dependency on a particular UI, provider or standalone identity
Tools and connectorsProvider/file operations, schemas, feature discovery and source-specific change semanticsSame adapters for every consuming host; no application layout or product accounts
Application servicesDefinitions, bindings, domain state, projections, action records and synchronization lifecycleHost-owned storage and authorization; independently testable, optional services
PresentationComponent registry, navigation, responsive layout, forms, selections, editor buffers and accessibilityTyped data/action bridge; no provider tokens or direct privileged execution
HostAuthenticated identities, grants, secrets, storage, worker limits and installed component versionsExplicit construction and shutdown; no central OpenAgent account dependency

This architecture places application services alongside the standalone's existing dashboards. Embedding hosts can supply their own services and renderers using the same public capability boundaries. Reusable services can be extracted into versioned packages when their contracts are qualified. This decision adds no required kernel module, source overlay, new central service or adopter-specific code.

Contracts to preserve ​

The following names describe architectural roles. They are not new configuration keys, callable endpoints or a published wire schema.

Application definition and component registry ​

A definition identifies its schema version, immutable revision, component dependencies, required capabilities, named source slots, views, actions and state migrations. It stores references to grants rather than credentials. Importing a definition never imports another person's access. The receiving host resolves each source slot with its own authorized configuration.

Components declare typed properties, outputs, interaction events and supported renderer versions. Layout and data adapters are independent: changing a source does not require rewriting a view, and changing a view does not change an operation's permissions. Collections, relations, selection, navigation, validation, drag operations and text editing must be expressible through composable contracts rather than a fixed set of provider-specific screens.

The renderer registry must admit versioned extensions with explicit host installation and compatibility checks. A portable subset must have defined fallbacks when a renderer is unavailable. Responsive layouts retain access to data and actions on narrow screens; keyboard operation, focus, loading, empty, partial, stale and error states are part of the component contract. CLI and non-graphical hosts use the same application services without pretending to render a graphical editor.

An application definition cannot add executable JavaScript, arbitrary native code or new privileges merely by naming a component. Trusted renderer code and explicitly configured command capabilities retain their existing installation and execution policy. View content is data, not authorization.

Source bindings and resources ​

A provider name is not a connection identity. Each binding resolves to a specific installation, tenant, principal/grant, connection, executor and resource scope. Two accounts of the same provider are distinct sources, as are two computers exposing the same filesystem tool. Source slots and display names never let an action substitute another account or device.

A resource reference preserves its source identity, provider-native identifier, type and available version token. File references also preserve filesystem/root identity; paths are interpreted only by their bound executor. Names and paths alone are insufficient global identifiers. Copies across sources receive new identities and explicit provenance rather than silently becoming one object.

Bindings declare schemas for reads, mutations, relationships, pagination, changes and errors, and advertise which features are actually supported. The application can compose typed projections while retaining source attribution and domain semantics, such as time zones, ordering, text encoding or binary content. It must not flatten every provider into a lossy universal record. Unsupported features have explicit capability results and UI states.

Collection queries need typed filtering, sorting, pagination and bounded incremental delivery, with their actual source limitations exposed. Large collections and file contents must be loaded on demand rather than copied wholesale into the model context or renderer. Query parameters cannot alter the binding's identity or resource grant.

Combining sources does not combine their permissions. Reads, joins, search, counts, exports and subscriptions must authorize both input resources and the result audience. One authorized source cannot reveal another's contents or metadata. Partial results identify unavailable sources only to an audience already permitted to know those bindings.

Actions and durable state ​

Every action binds its target source, validated input/output schemas, required permissions, execution location, expected resource version and applicable idempotency policy. The host resolves current capabilities at execution time; persisted definitions never retain an expired opaque ToolRef or client lease. UI, CLI and agent invocation converge on the same service and authorization path. A read-only view does not imply permission to mutate its backing source. Shared services do not automatically advertise App-only tools to other channels or background runs; the host still selects and authorizes each surface.

State has separate lifecycles:

StateAuthority and persistence
Definition and view revisionImmutable, checksummed configuration with explicit migrations
Application-owned recordsDurable host data with ACLs, versions, backup and recovery
Source projection/cacheDerived data with provenance, cursor, freshness and rebuild procedure
Pending mutation and outcomeDurable intent and reconciliation record; never a cache
UI stateSelection, navigation and drafts scoped to the user/device; durability declared explicitly

Saving a view or publishing a new layout must not reset records, drafts or synchronization checkpoints. Rebuilding a cache must not discard unsent edits. A locally persisted projection is not evidence of a successful provider write. Attachments use authorized content references rather than exposed host paths.

Actions that span providers are not a distributed atomic transaction. Each step records its outcome; partial completion is visible and recovery or compensation is explicit. Writes with an ambiguous outcome are reconciled before another attempt. Provider-supported idempotency and conditional updates are used where available; application code must not promise exactly-once external effects.

Synchronization and background work ​

Synchronization is a lifecycle owned by the host application service, not by an open chat transcript or a visible component. Each source/resource partition has independent checkpoints, ordering/version semantics and health. Webhooks, change streams and bounded polling are interchangeable only where the source's declared contract permits it. One failed account does not block healthy ones.

The synchronization contract must specify initial pagination, incremental updates, deletion/tombstones, duplicate and out-of-order delivery, cursor expiry, full rescan, rate limits and restart recovery. Checkpoint advancement and local projection changes commit consistently. Durable jobs deduplicate delivery and bound retries, concurrency, memory, disk and retention. Idle sources must not create a polling storm; subscriptions can share work only within compatible authorization and resource boundaries.

Edits carry their observed revision or ETag. Concurrent changes produce a documented source-specific merge, a conflict to resolve, or an explicit lack of conditional-write support. There is no universal last-writer-wins policy and no assumption that all sources support collaborative text editing. Offline drafts and queued writes require declared support, reauthorization before execution and reconciliation after reconnect.

An interactive device capability remains temporary. A background job cannot reuse the last online computer or a saved client connection. Device-only work waits for a new authorized interaction, or uses a separately configured durable executor with its own grant. See Client Computer Tools.

Revoking a connection stops new reads, writes and subscriptions for that grant. Outstanding work and cached data follow explicit cancellation, retention and privacy policy. A shared view cannot retain a revoked participant's access. Operational logs record identities, versions, progress and outcomes without copying credential values or document bodies.

Existing foundations and remaining work ​

These observations describe the source inspected for this decision, not new installed-product acceptance.

Foundation in the current sourceArchitectural work still required
Public Core capability catalog, verified principals, exact executor binding and optional durable modulesQualify application bindings and action dispatch against those public contracts
Product Custom Views: validated OA-UI v1, typed built-in components, immutable bundles and revisions, ACLs, source state and subscriptionsVersioned component extension and application-definition contracts; richer interactive renderer support
Static/push/file-watch/command data drivers; bounded commands and action schemasTyped provider-source driver contract with per-account cursors and feature negotiation
View revision checks, expected-version data updates, data replace/merge/append and action-run idempotency recordsSeparate durable application records, draft policy and provider mutation reconciliation/conflict handling
Shared connector adapters and product-owned connection credentialsMulti-source application binding policy and explicit authorization of combined results
Authenticated artifact routes and immutable view referencesQualified editing/save lifecycle; artifact download alone does not provide document editing

Existing mcp_tool dashboard actions name a server/tool and use the configured MCP bridge; command actions use explicitly configured subprocesses. Neither is evidence that a generic application action contract, provider synchronization or versioned renderer plugin API is complete. Extending this path must converge on public capability dispatch while preserving existing views, saved IDs, permissions and the temporary App-origin boundary. Unknown definitions or unsupported versions fail explicitly instead of silently changing behavior.

The current OA-UI code and markdown components display content. Their existence does not establish an editor, save protocol or multi-filesystem synchronization. Similarly, data-source updates and view subscriptions are not proof of a durable bidirectional synchronization engine.

Acceptance and implementation sequence ​

Future implementation proceeds through bounded contracts: source bindings and action dispatch, durable state and reconciliation, renderer registration and compatibility, then source-specific synchronization. Each can be delivered independently without adding one of the reference applications to Core.

Qualification uses neutral fake sources and synthetic records before real provider acceptance. It must establish:

  • Two accounts of one adapter and a second adapter can supply one view without identifier collisions or accidental cross-account writes.
  • Two views use the same service/state and independent UI selections; schema upgrades preserve data and reject unsupported component versions.
  • Permissions and result audiences are checked for each binding, including derived data, offline drafts, revocation and resumed background work.
  • Repeated/out-of-order changes, pagination, cursor expiry, missed events and a restart recover without lost records or duplicate external effects.
  • A concurrent edit and an ambiguous write have observable conflict/recovery outcomes; a source outage leaves healthy sources usable with honest freshness.
  • Different filesystem executors with identical paths remain distinct; editor drafts preserve encoding/version and never overwrite a changed file silently.
  • Narrow and wide layouts, keyboard interaction and unavailable component/source states remain usable without requiring a model call per UI interaction.
  • Disabling an optional module/source removes its execution surface, preserves host-owned data under policy and never falls back to another executor.

These are architecture acceptance gates. They do not assert that a calendar, task tracking system or document editor has been implemented or qualified.