How Agents Discover Capabilities at Install Time: The <app>.help Convention
When you install a tool into your agent's runtime, the agent needs to know how to use it. Not just that it exists — what methods it exposes, what parameters each method expects, what it costs to call, and whether it's fast enough to use in a tight loop. That metadata has to come from somewhere.
Most tooling ecosystems skip this: they hand the agent a schema file (OpenAPI, JSON Schema, function definition) and hope the agent can figure out the rest. The agent loads the schema, makes a blind guess at latency and cost, and either wastes tokens on a description field that says "this method does X" or finds the description empty.
The <app>.help convention solves this differently. It makes runtime discovery of a capability's full surface area a first-class, contract-level operation — not a documentation afterthought.
The Problem: Agents Can't Ask "What Can You Do?"
A tool installed into an agent runtime is a black box. The agent knows the tool's name and maybe a one-liner description from the install manifest. That's it. Everything else — method list, parameter names and types, latency characteristics, cost — lives in external documentation the agent has to fetch, scrape, or hallucinate.
This creates four concrete problems:
- The agent can only use tools it has been explicitly coded or prompted to use. There's no runtime discovery loop where an agent evaluates a new tool's capabilities and plans a call it has never made before.
- Latency and cost are invisible until the call fails or the bill arrives. An agent can't look at a tool and say "this one is fast enough for a real-time loop" or "this one costs $0.01 per call."
- Every tool needs a bespoke integration. There's no standard way to discover a tool's method surface — every registry or plugin system reinvents the same thing slightly differently.
- The agent is always one version behind. The tool evolves, but the agent's understanding of it doesn't, because discovery only happens at build/install time, not at call time.
The <app>.help Convention: A Capability That Self-Describes
The <app>.help convention solves all four problems with one rule: every installed capability exposes a .help method that returns a machine-readable manifest of everything the agent needs to plan a call.
Here's what that looks like in practice. After installing an app via the app store:
pilotctl appstore install io.pilot.cosift --force
# daemon auto-spawns it
pilotctl appstore list
# state should be "ready"
The agent then calls .help to discover the app's surface:
pilotctl appstore call io.pilot.cosift cosift.help '{}'
The reply is a structured JSON object — not a wall of prose. It lists every method the app exposes, the exact parameter names and types each method expects, and a latency class and cost estimate for each:
{
"methods": [
{
"name": "search",
"params": {
"q": {"type": "string", "required": true, "description": "Search query"},
"k": {"type": "integer", "required": false, "default": 5, "description": "Top-k results"},
"freshness": {"type": "string", "required": false}
},
"latency": "fast",
"cost": null
}
]
}
The latency classes are standardised: fast (<1s), med (1-5s), slow (5-30s). The agent reads these values, compares them against its runtime constraints, and decides whether to call the method and how to fit it into a plan.
Why This Matters for Autonomous Agents
The <app>.help convention turns tool installation from a one-time build-time event into a continuous runtime capability. Here's what changes:
1. An Agent Can Use a Tool It Has Never Seen Before
A stock agent that has never encountered cosift receives cosift.help and learns:
- There's a method called
search - It takes a
q(string, required) andk(integer, optional) - It's
fast(<1s) and costs nothing
The agent can now construct a valid cosift.search call without any prior training data, prompt engineering, or bespoke integration code. The discover→plan→call loop is fully runtime.
2. An Agent Can Choose Between Tools by Capability
If both cosift.search and plainweb.toMarkdown are installed, the agent can ask each for its .help and decide which to use based on latency, param shape, and cost — without hardcoded routing logic.
# cosift.help shows: search {q, k} — fast, free, returns structured citations
# plainweb.help shows: toMarkdown {url} — med, free, returns raw markdown
# Agent decides: "user wants cited answers about a topic" → cosift.search
# "user wants the content of one specific page" → plainweb.toMarkdown
3. Version Drift Stops Being a Problem
When an app updates and adds a new method or parameter, the agent's next .help call already reflects the change. No restart, no reinstall, no documentation sync. The agent adapts its calls to the current surface on every invocation.
How It Compares to Other Approaches
Schemas (OpenAPI, JSON Schema, function definitions) are static documents shipped at build time. They describe the shape of a request and response but tell the agent nothing about runtime characteristics — how long a call takes, what it costs, or whether the service is currently available.
MCP tools expose a tools/list endpoint that returns a tool list with JSON Schema parameter descriptors, which is the closest prior art. It solves the "what methods and params exist" problem at runtime. What it doesn't do is standardise latency, cost, or the discover→plan→call loop. The agent gets a schema and has to guess everything else.
The <app>.help convention builds on the same idea but adds runtime characteristics as first-class fields — latency class, cost, and an explicit contract that every capability must report its surface. It's designed for agents that need to make autonomous, unplanned decisions about which tool to use and how to call it, not for humans reading documentation and wiring up integrations.
The Loop: Discover → Install → .help → Call
The full lifecycle is four commands, all runtime:
# 1. Discover what's available
pilotctl appstore catalogue
# 2. Install the capability
pilotctl appstore install io.pilot.sixtyfour --force
# 3. Discover its surface at runtime
pilotctl appstore call io.pilot.sixtyfour sixtyfour.help '{}'
# 4. Call a method with the exact params from .help
pilotctl appstore call io.pilot.sixtyfour sixtyfour.search '{"prompt": "work email for a person given name + company"}'
Steps 2-4 can be done in any order, repeated any number of times, by any agent on the network. No build step, no deploy, no documentation update.
What It Means for Tool Builders
If you're building a capability for agents — a search index, a database connector, an enrichment API, a microVM runner — the sharpest competitive advantage you can give your app is a good .help response. The agent reads it. The agent plans from it. If your .help is complete, the agent will use your app correctly on the first try, without a single line of integration code written by a human.
The standard is simple:
- Every method gets a
latencyclass (fast/med/slow) - Every parameter is typed, marked required or optional, and has a description the agent can act on
- If the call costs money, the price is in the response
That's it. The rest is JSON structure and good naming.
The app store model — discover → install → .help → call — is built for this. Publish an app, and the .help convention makes it instantly usable by any agent on the network, with no documentation, no example code, and no onboarding call.
The <app>.help convention is part of the Pilot Protocol app store. To try it: curl -fsSL https://pilotprotocol.network/install.sh | sh then pilotctl appstore catalogue.
Top comments (0)