Skip to content

Portable agent format

bnw.agent-manifest/1 is the first Milestone 9 application profile. It describes a portable agent without binding that agent to one machine, model provider, tool server, or centralized scheduler.

The manifest is an immutable descriptor carried by an ordinary agent.portable capability manifest. The outer BNW capability identifies the publisher and logical subject. The descriptor references immutable instructions and exact stable capabilities required to run the agent.

An agent manifest contains:

  • a display name and optional description;
  • one immutable instructions content ID;
  • 1–64 required roles, each bound to one exact capability ID;
  • up to 32 immutable policy content IDs;
  • an optional exact memory capability ID; and
  • the fixed agent/run input/output contract.

Requirement roles are machine-safe local names such as model, search, or finance-data. Roles must be unique. Version 1 uses exact capability IDs deliberately: fuzzy constraints, pricing, ranking, and automatic substitutions require explicit later resolution semantics.

Instructions and policies are references, not embedded authority. Their content, confidentiality, availability, and interpretation remain application concerns. A capability reference identifies a signed stable definition; a later resolver must still find acceptable active provider offers and apply local trust and authorization policy.

First store the instructions and any policy documents as immutable BNW blobs. Record the printed blob IDs:

Terminal window
bnw blob put agent-instructions.md --media-type text/markdown
bnw blob put agent-policy.json --media-type application/json

Create the portable manifest. Repeat --require for every exact dependency and --policy for every policy object:

Terminal window
bnw capability descriptor create-agent portable-agent.json \
--name "Portable research agent" \
--description "Researches a topic using fixed model and search capabilities" \
--instructions <INSTRUCTIONS_BLOB_ID> \
--require model=<INFERENCE_CAPABILITY_ID> \
--require search=<SEARCH_CAPABILITY_ID> \
--policy <POLICY_BLOB_ID> \
--memory <MEMORY_CAPABILITY_ID>

The command sorts requirements and policies into their deterministic representation, validates every identifier and bound, stores the descriptor locally, and prints its content ID.

Validate, inspect, and publish it:

Terminal window
bnw capability descriptor validate portable-agent.json
bnw capability descriptor inspect <AGENT_DESCRIPTOR_ID>
bnw capability publish agent.portable <AGENT_DESCRIPTOR_ID>

Another peer can discover and follow the agent through the existing bounded capability path:

Terminal window
bnw capability discover agent.portable
bnw capability list --kind agent.portable
bnw capability inspect <AGENT_CAPABILITY_ID>
bnw capability follow <AGENT_CAPABILITY_ID>

Publishing an agent manifest does not execute it, grant access to its dependencies, or endorse their providers. Version 1 establishes the immutable portable definition. Local resolution checks each exact requirement against canonical manifests and active provider offers while retaining missing and policy-rejected outcomes rather than hiding them behind a global scheduler.

After following and synchronizing every referenced capability, resolve the agent locally:

Terminal window
bnw agent resolve <AGENT_CAPABILITY_ID>

The resolver validates each exact capability and descriptor, ignores expired and zero-slot offers, collapses offer renewals by provider, and selects a stable local candidate. Economic constraints are optional:

Terminal window
bnw agent resolve <AGENT_CAPABILITY_ID> \
--credit-issuer <ISSUER_BNW_ID> \
--max-per-invocation-micros 5000000

Prices are compared only within one issuer’s service-credit system. See ECONOMICS.md. Resolution does not invoke dependencies, reserve credits, or grant authority.

Capabilities → Provide a capability → Agent publishes a manifest: name, description, instructions, and requirements by role, each picked from the catalog. The node stores the instructions as a blob, sorts the requirements by role, and publishes the capability, as capability descriptor create-agent and capability publish agent.portable do. The form warns when no inference.model requirement is present.

The requirement picker filters the catalog by kind on the node and by name in the browser, and can load more pages.

Policies, memory, and the run contract, a collapsed section of the form, covers what the CLI flags do:

  • Policies. Texts separated by a line holding only ---, at most 8 from the web client. Each becomes an immutable blob, and the manifest lists their content IDs, sorted.
  • Memory. An exact memory capability.
  • The agent/run contract. Media types, size limits, privacy, and optional JSON Schemas.

Published agents appear under My capabilities. They need no offer or backend, because they run on whichever node adopts them.

An agent.portable capability’s page shows the instructions, fetching them from peers when missing. The publisher’s node, and every node that follows the agent, serves its instructions and policies, so they can be fetched while the publisher is offline. It also shows each requirement with the provider and terms the resolver would choose, or the reason there is none.

An agent hosted on your node can be published as a portable agent from its page: Publish as portable agent opens the Agent form, filled in from how the agent runs now. The form includes its name, its instructions (or the built-in ones), its model as the model requirement, and each tool its operators let it use as tool-1, tool-2, and so on. Review it, then publish.

  • Signing. The node signs the manifest as its publisher and names the hosted agent as its subject, so the catalog shows which agent it describes. The agent’s own key first delegates capability:publish to the node for a year, renewed on a later publish when less than a month remains. Other nodes verify that delegation before they show the node’s authority over the agent.
  • Access. Publishing grants nothing. Whoever runs the agent needs their own access to its model and tools.
  • Instructions. They become a blob anyone who finds the agent can fetch, so keep secrets out of them.

Run this agent here (or bnw agent runtime --from-manifest <AGENT_CAPABILITY_ID> [--enable]) configures the node’s agent runtime from the manifest:

  • the instructions;
  • its inference.model requirement as the model (preferring the role model);
  • the resolved provider of that model.

It is refused in these cases, with the reason shown:

  • the instructions are not local yet;
  • they exceed the runtime’s 8 KiB limit;
  • there is no model requirement;
  • the model has no offer;
  • the only offer belongs to the node’s own identity, which cannot invoke itself.

Other requirements are tools. The agent’s operators still decide which of them it may use, through agent:invoke grants.