Composable Mini-Apps
Rule
Prefer many one-job apps in a workspace over one oversized app. A headless app
can own a provider, dataset, workflow, or specialist action surface without a
full UI; the main agent composes those apps through discovery and A2A.
Shape
- Give each mini-app one clear job, a concise
package.json description, and
action names that describe the job it owns.
- Keep provider credentials and upstream API details in the app that owns that
provider or workflow. Other apps should delegate to it instead of copying its
integration code.
- Use a tiny status/config screen only when users need to inspect state. A
pure headless app is fine when its job is invoked by agents, automations, or
sibling apps.
- If two workflows only share a helper, put the helper in
packages/shared;
keep the workflow actions in separate apps.
Discovery And Invocation
The main agent should discover available siblings before assuming capability:
- Runtime agents receive an
<available-apps> block built from
discoverAgents(). Workspace siblings are layered in by
discoverWorkspaceAgents(). It carries one line per app — enough to know a
sibling exists, not enough to know what it can do.
- Use the built-in
describe-workspace-apps tool for actual capability.
It reads each peer's live /.well-known/agent-card.json and returns its
purpose plus any optional stable machine contracts; pass app: "<id>" for
one peer's full description. Call it before building something a sibling may
already own, before telling a user what is or is not possible across apps,
and whenever someone asks which app to use for a job.
- Never hand-maintain a markdown or code list of what each workspace app does.
A stale catalog is worse than none: it reads as authoritative while pointing
at capabilities that moved or vanished. An app's purpose belongs in its own
package.json description (which flows into the workspace manifest and the
<available-apps> block), and its capabilities belong in its exposed
actions — both of which describe-workspace-apps reads live.
- UI shells, headless surfaces, and scripts can read the same registry through
GET /_agent-native/agents?selfAppId=<app-id>.
- Code or CLI callers should use the first-class message-based A2A invocation
path (
invokeAgent() / agent-native invoke) when they need to ask an app
by id, name, or URL.
- In the agent loop, use
call-agent with the sibling app id when another app
owns the work or data. Never call the current app through call-agent; use
local actions instead.
- Send a natural-language objective by default so the sibling can apply its own
instructions, skills, schemas, data dictionary, credentials, and tools.
invokeAgentAction() or call-agent with action + input is only for an
explicit stable semantic read contract whose complete input is already known.
Never expose or call an implementation action as a workaround for slow or
failed message delegation.
Send narrow prompts to siblings: name the exact question, relevant ids, date
ranges, and expected output shape. Preserve returned ids and URLs verbatim.
Artifact Handoff
Mini-apps should hand off compact artifacts, not giant pasted transcripts or
provider dumps. When a mini-app creates something another app may use, return
or store an artifact with:
artifactType - what kind of output this is, such as deal-set,
call-evidence, brief, dashboard, or report.
artifactId - the stable app-owned id, file path, or resource id.
createdAt - an ISO timestamp.
source - provider/app/source ids used to create it.
summary - a short human-readable explanation.
items or records - the bounded structured data downstream apps need.
links - fully qualified URLs for user-visible artifacts.
Downstream apps should receive artifact ids, URLs, and narrow follow-up
questions. If a downstream app needs more detail, it should call back to the
artifact-owning app instead of asking the orchestrator to paste the whole
corpus into a prompt.
Example: hubspot-pipeline returns { artifactType: "deal-set", artifactId: "hubspot-pipeline:deal-set:2026-06-18" }. deal-brief passes
that id to gong-evidence, which returns a call-evidence artifact id and
URLs. deal-brief then synthesizes the final brief from the artifact ids and
bounded summaries.
Provider APIs
Provider-specific actions are shortcuts, not limits. When the upstream API can
answer the question better than a first-class shortcut, call
provider-api-catalog and provider-api-docs as needed, then
provider-api-request against the real provider endpoint. For broad joins,
searches, or absence claims, stage the bounded corpus with stageAs and reduce
it with query-staged-dataset or code.
When composing apps, make the provider-owning mini-app do those
provider-api-request calls. The orchestrator should delegate a bounded job;
it should not reimplement every provider endpoint locally.
Example
For a sales-intelligence workspace, split the job into small apps:
| App |
Owns |
Calls |
hubspot-pipeline |
CRM deals, contacts, companies, associations |
provider-api-request with provider hubspot |
gong-evidence |
Calls, transcripts, snippets, speaker evidence |
provider-api-request with provider gong |
knowledge-base |
Internal docs, pricing rules, playbooks |
local search/read actions |
deal-brief |
Orchestration and final brief |
message-based invokeAgent() or call-agent to the three apps |
Flow: deal-brief asks hubspot-pipeline for the target account and open
deals, asks gong-evidence for recent transcript evidence about those deals,
asks knowledge-base for relevant playbook guidance, then synthesizes the
answer. That is a HubSpot→Gong→knowledge-base chain made of focused apps,
not a single app that clones every provider integration.
Don't
- Do not clone Mail, Calendar, Analytics, Brain, Assets, or another first-party
app just to reuse its data. Delegate or link to the existing app.
- Do not hide a multi-provider workflow inside a giant "misc tools" app.
- Do not add one-off provider endpoints when
provider-api-request can express
the upstream API safely.
- Do not create wrapper routes that only re-export another app's action or A2A
result.
Related Skills
- a2a-protocol - How apps expose and call A2A endpoints.
- actions - How each mini-app exposes its own operation surface.
- external-agents - How external MCP hosts route through workspace apps.
- storing-data - How app-owned data stays SQL-backed and portable.
1---2name: composable-mini-apps3description: Build many focused workspace apps that compose through agent discovery and A2A. Use when designing headless mini-apps or cross-app workflows.4---56# Composable Mini-Apps78## Rule910Prefer many one-job apps in a workspace over one oversized app. A headless app11can own a provider, dataset, workflow, or specialist action surface without a12full UI; the main agent composes those apps through discovery and A2A.1314## Shape1516- Give each mini-app one clear job, a concise `package.json` description, and17 action names that describe the job it owns.18- Keep provider credentials and upstream API details in the app that owns that19 provider or workflow. Other apps should delegate to it instead of copying its20 integration code.21- Use a tiny status/config screen only when users need to inspect state. A22 pure headless app is fine when its job is invoked by agents, automations, or23 sibling apps.24- If two workflows only share a helper, put the helper in `packages/shared`;25 keep the workflow actions in separate apps.2627## Discovery And Invocation2829The main agent should discover available siblings before assuming capability:3031- Runtime agents receive an `<available-apps>` block built from32 `discoverAgents()`. Workspace siblings are layered in by33 `discoverWorkspaceAgents()`. It carries one line per app — enough to know a34 sibling exists, not enough to know what it can do.35- Use the built-in `describe-workspace-apps` tool for actual capability.36 It reads each peer's live `/.well-known/agent-card.json` and returns its37 purpose plus any optional stable machine contracts; pass `app: "<id>"` for38 one peer's full description. Call it before building something a sibling may39 already own, before telling a user what is or is not possible across apps,40 and whenever someone asks which app to use for a job.41- Never hand-maintain a markdown or code list of what each workspace app does.42 A stale catalog is worse than none: it reads as authoritative while pointing43 at capabilities that moved or vanished. An app's purpose belongs in its own44 `package.json` `description` (which flows into the workspace manifest and the45 `<available-apps>` block), and its capabilities belong in its exposed46 actions — both of which `describe-workspace-apps` reads live.47- UI shells, headless surfaces, and scripts can read the same registry through48 `GET /_agent-native/agents?selfAppId=<app-id>`.49- Code or CLI callers should use the first-class message-based A2A invocation50 path (`invokeAgent()` / `agent-native invoke`) when they need to ask an app51 by id, name, or URL.52- In the agent loop, use `call-agent` with the sibling app id when another app53 owns the work or data. Never call the current app through `call-agent`; use54 local actions instead.55- Send a natural-language objective by default so the sibling can apply its own56 instructions, skills, schemas, data dictionary, credentials, and tools.57 `invokeAgentAction()` or `call-agent` with `action` + `input` is only for an58 explicit stable semantic read contract whose complete input is already known.59 Never expose or call an implementation action as a workaround for slow or60 failed message delegation.6162Send narrow prompts to siblings: name the exact question, relevant ids, date63ranges, and expected output shape. Preserve returned ids and URLs verbatim.6465## Artifact Handoff6667Mini-apps should hand off compact artifacts, not giant pasted transcripts or68provider dumps. When a mini-app creates something another app may use, return69or store an artifact with:7071- `artifactType` - what kind of output this is, such as `deal-set`,72 `call-evidence`, `brief`, `dashboard`, or `report`.73- `artifactId` - the stable app-owned id, file path, or resource id.74- `createdAt` - an ISO timestamp.75- `source` - provider/app/source ids used to create it.76- `summary` - a short human-readable explanation.77- `items` or `records` - the bounded structured data downstream apps need.78- `links` - fully qualified URLs for user-visible artifacts.7980Downstream apps should receive artifact ids, URLs, and narrow follow-up81questions. If a downstream app needs more detail, it should call back to the82artifact-owning app instead of asking the orchestrator to paste the whole83corpus into a prompt.8485Example: `hubspot-pipeline` returns `{ artifactType: "deal-set",86artifactId: "hubspot-pipeline:deal-set:2026-06-18" }`. `deal-brief` passes87that id to `gong-evidence`, which returns a `call-evidence` artifact id and88URLs. `deal-brief` then synthesizes the final brief from the artifact ids and89bounded summaries.9091## Provider APIs9293Provider-specific actions are shortcuts, not limits. When the upstream API can94answer the question better than a first-class shortcut, call95`provider-api-catalog` and `provider-api-docs` as needed, then96`provider-api-request` against the real provider endpoint. For broad joins,97searches, or absence claims, stage the bounded corpus with `stageAs` and reduce98it with `query-staged-dataset` or code.99100When composing apps, make the provider-owning mini-app do those101`provider-api-request` calls. The orchestrator should delegate a bounded job;102it should not reimplement every provider endpoint locally.103104## Example105106For a sales-intelligence workspace, split the job into small apps:107108| App | Owns | Calls |109| --- | --- | --- |110| `hubspot-pipeline` | CRM deals, contacts, companies, associations | `provider-api-request` with provider `hubspot` |111| `gong-evidence` | Calls, transcripts, snippets, speaker evidence | `provider-api-request` with provider `gong` |112| `knowledge-base` | Internal docs, pricing rules, playbooks | local search/read actions |113| `deal-brief` | Orchestration and final brief | message-based `invokeAgent()` or `call-agent` to the three apps |114115Flow: `deal-brief` asks `hubspot-pipeline` for the target account and open116deals, asks `gong-evidence` for recent transcript evidence about those deals,117asks `knowledge-base` for relevant playbook guidance, then synthesizes the118answer. That is a HubSpot→Gong→knowledge-base chain made of focused apps,119not a single app that clones every provider integration.120121## Don't122123- Do not clone Mail, Calendar, Analytics, Brain, Assets, or another first-party124 app just to reuse its data. Delegate or link to the existing app.125- Do not hide a multi-provider workflow inside a giant "misc tools" app.126- Do not add one-off provider endpoints when `provider-api-request` can express127 the upstream API safely.128- Do not create wrapper routes that only re-export another app's action or A2A129 result.130131## Related Skills132133- **a2a-protocol** - How apps expose and call A2A endpoints.134- **actions** - How each mini-app exposes its own operation surface.135- **external-agents** - How external MCP hosts route through workspace apps.136- **storing-data** - How app-owned data stays SQL-backed and portable.