CtrlK
BlogDocsLog inGet started
Tessl Logo

composable-mini-apps

Build many focused workspace apps that compose through agent discovery and A2A. Use when designing headless mini-apps or cross-app workflows.

66

Quality

80%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

Fix and improve this skill with Tessl

tessl review fix ./.agents/skills/composable-mini-apps/SKILL.md
SKILL.md
Quality
Evals
Security

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 their callable action names; pass app: "<id>" for one peer's full list with descriptions. 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 A2A invocation path (invokeAgent() / agent-native invoke) when they need to call 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.
  • When the exact sibling-owned read action and input are already known, use invokeAgentAction() or call-agent with action + input. This preserves the receiver's credentials and access checks while skipping its second model loop. Use prompt-based invokeAgent() only when the sibling must reason, synthesize, mutate, or perform a multi-step workflow.

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:

AppOwnsCalls
hubspot-pipelineCRM deals, contacts, companies, associationsprovider-api-request with provider hubspot
gong-evidenceCalls, transcripts, snippets, speaker evidenceprovider-api-request with provider gong
knowledge-baseInternal docs, pricing rules, playbookslocal search/read actions
deal-briefOrchestration and final briefinvokeAgent() 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.
Repository
BuilderIO/agent-native
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.