Section 6 of the specification

The Agent Descriptor

The operator's standing description of one agent, and the primary location for its metadata.

version 0.27.0-draft status Working draft date 2026-10-17

This page renders Section 6 of the Common Agent Specification 0.27.0-draft. Where the two differ, the full specification governs. Section numbers are the specification's own, so a reference such as Section 4.1 is in the full text. Rendered 2026-10-17 from SPEC.md in the Common Agent Standards repository, tag common-agent-v0.27.0-draft, commit 00ec3e61.

The declaration surface is the Agent Descriptor: the operator's standing description of one agent, and the primary location for its metadata. What it does, what each offering takes and returns, who drives it, what it refuses, and where it runs, in one document, signed once bound, versioned by replacement, referenced at a digest. This chapter is the Descriptor's normative definition; the page at https://commonagent.net/descriptor.html is a rendering of it.

6.1 Primary, and others bind#

An agent's facts end up spelled in several places: a description on a card, offerings on a registration, inputs in a contract, a model name in a config. Two spellings of one fact drift, and then a reader cannot tell which one the operator means. The Descriptor exists to end that: it is the one place the operator writes, and everything else derives from it or points into it.

A fact about the agent appears in the Descriptor once. A card or a manifest MAY carry a copy of a Descriptor fact, but only as a projection: derived from the Descriptor, never edited independently. A signed document that wants to make a Descriptor fact binding references it at a digest (Section 6.5) rather than restating it. A document that spells a Descriptor fact a second time, in its own words, does not conform to this section.

What the Descriptor is not: it is not a card, because it carries no endpoint and no authentication, which are connection facts, and the Descriptor holds shapes only (Section 6.4). It is not a contract: nothing in it binds anyone until a signed proposal references it. And it is not evidence: nothing issued by a third party after something happened is a member of it. Verdicts, records, and reputation check the Descriptor from outside.

6.2 The document#

A Descriptor is a JSON object. Three members are required in every Descriptor, draft or bound:

Member Holds
format Which version of the Agent Descriptor format this document follows. For this specification it MUST be "agent-descriptor-v1".
agent_version Which version of the agent this describes, in the operator's own scheme. Two Descriptors for the same subject are ordered by it.
does One sentence on what the agent does.

The subject, draft and bound. The subject member holds the agent's key and handle: { "id": <public key>, "handle": <handle> }. A draft leaves subject absent, because a builder describes agents that do not exist yet; the subject is filled at deployment, when the agent receives its identity. Nothing binds to a draft: a signed proposal MUST NOT reference a Descriptor without a subject, and a registry MUST NOT store one as an agent's Descriptor. Once bound, a Descriptor's subject MUST NOT change. A new agent gets a new Descriptor, not an edited one.

Whom it acts for. acts_for says whom the agent represents to the parties it deals with. It is one of three values:

Value The agent
person Acts for one person, its owner. It is a personal agent, the same thing Section 7.8 and PACT call a personal agent.
organization Acts for a business or a team. It MAY name the organization in organization_name, a name the organization is publicly known by and never an address or an account identifier (Section 6.4, rule 3).
anyone Is a public service with no principal. It still has an operator who answers for it (Section 2), and it represents no person and no organization to the parties it serves.

acts_for is REQUIRED in a bound Descriptor written under this version or later. It is decided at install, by whoever decides who owns the agent, so a draft does not carry it (Section 12.6, rule 4). A Descriptor that lacks it, including every Descriptor written before this version, is read as not stated, and a reader MUST NOT guess a value from the agent's name, its description, its offerings or its interaction. organization_name appears only beside organization. The consent rules that read this member are Section 6.9's.

Offerings. offerings[] carries one entry per hireable thing. Each entry has an id, a name, one sentence of description, and its inputs and outputs. It MAY carry scope, and the members its scope requires, as Section 6.11 says; an offering without scope is named work with the inputs and outputs below, which is what every offering declared before 0.27.0-draft meant:

  • inputs[]: each input's name, its kind (Section 6.3), whether it is required, and external: true when it is reached rather than furnished. An input that is a grant rather than a thing sent MAY carry via, one or more values from Agent SoW's grant-mechanism vocabulary, naming the mechanisms the operator accepts for making the grant. A caller reads it before deciding whether to engage, which is the point of stating it here. An input MAY carry one_of, a group name: at least one input of the offering naming that group MUST arrive, and no member of the group is required on its own, so an agent that reads any one of five kinds of source says so once instead of marking all five optional and leaving the caller to read an agent that needs nothing. A consumer that does not know the member reads each as optional, the weaker claim, which is the safe direction to fail in. An input MAY carry max_bytes, the most of it the agent takes: a caller, and anything that hands work on, checks it before sending and, over it, says so and sends nothing, because an agent handed part of an input does part of the work without knowing it. An agent that works inside a process MAY declare an input of kind application/vnd.agentmesh.run-context+json, named run-context, with fields naming what it reads (for example focus and audience): the run context, the answers the run was started with, which a process runner hands to every step whatever its place in the process. A consumer that does not know either member loses nothing by ignoring it.
  • outputs[]: each deliverable's name, its kind, and when: per_task for a deliverable each task produces, standing for one maintained across tasks. An output MAY carry working: true when it is the agent's working out, filed so a reader can check the deliverable against where it came from, rather than the deliverable itself; a renderer lists the deliverables first and MUST NOT drop the working pieces, because a caller still receives them.

Revisions. An offering MAY carry revisions, what a change to its delivered work costs (Section 5.7): included, with a count and a window_days after the first delivery, and either steps[], each a step id from the offering's own steps[] (Section 12.3) with a price in the price declaration's shape, or flat, one price for any revision. An offering without revisions does not offer them, and a request that names a prior task is refused as Section 5.7 says. The member is a declaration in the sense of Section 6.10: what it promises is enforced at the responder's node, and a document that promises what its node does not apply is not conformant.

The line between an input and a system: something furnished or named per task is an input, and something bound once at deployment and used across tasks is a system (systems[], below).

Interaction and refusals. interaction answers one question: is a person attending the agent right now. It is "interactive" when one is and "service" when nobody is in the loop, and the caller-side semantics are Section 6.9's. It says nothing about whom the agent acts for, which is acts_for, and nothing about how the agent is built: an agent that acts for a person may run as a service while its person is away, and a business's agent may be attended by a member of staff. refusals is prose: what the agent will not do, in the operator's own words. Refusals gain force elsewhere, as SoW clauses and role contracts; here they are the operator's plain statement.

Extensions. Every member beyond the core is optional, and an absent one means not stated (Section 6.4):

Member Holds
role The standard role held, by offering name. The contract stays at the roles registry.
interfaces[] The interfaces implemented, by name. The definitions stay at the registry.
fleet True when several processes answer as one identity (Section 4.1). It is a fact about the agent's identity and sits beside subject.
shape Read from a Descriptor written before 0.27.0-draft, and mapped member by member as Section 6.12 says. A writer MUST NOT emit it.
hosted_in[] The jurisdictions or regions the runtime sits in. A region, never an address. Distinct from where content is processed and where answers apply, which keep their own documents.
systems[] Standing systems the work is bound to: a name, an access level (read, write, trigger), and needs, what the access is for. The assembled view carries this as its reaches section (Section 9).
limits Per-caller ceilings: requests_per_hour, model_budget_per_day, and past_them, what happens beyond them. Each ceiling is a number, or { "most": <number>, "decided_by": "rule" | "model" }, which also says what holds the agent to it (Section 6.11); a bare number leaves that not stated.
handling_ref, price_ref, samples_ref Pointers to the data-use declaration, the price, and the samples document (Section 7.7), which keep their existing homes. The Descriptor points at them rather than restating them.
run_config What a job may set: the declared settings, the models the author tested, and the author's named run configs (below, and Section 5.8).

The member that names a system is name, and role is its alias for one revision. A reader MUST treat systems[].role and systems[].name as the same member, and MUST prefer name where a document carries both. A writer SHOULD emit name, and the alias is removed at the next revision. The rename is because role already names the standard job an agent holds, the first member in the table above, whose contract is an entry at the roles registry: one word for the job an agent takes on and for the name of a database it reaches makes a document nobody can read without being told which was meant.

Run configs. run_config declares what a run config may set for this agent (Section 5.8). Only a setting declared here can be set, at any layer.

"run_config": {
  "settings": [
    { "name": "model", "kind": "rule", "default": "example/model-a",
      "allowed": ["example/model-a", "example/model-b"], "job_may_set": false },
    { "name": "speaker", "kind": "preference", "default": "the deck's author",
      "allowed": ["the deck's author", "a narrator"], "job_may_set": true }
  ],
  "tested_models": ["example/model-a"],
  "named": [ { "name": "Deck explainer, Oct 6", "settings": { "speaker": "the deck's author" }, "digest": "sha256:…" } ]
}

Each entry in settings[] has a name, unique in the block; a kind, preference or rule, whose resolution Section 5.8 gives; a default; allowed; and job_may_set. allowed lists the values the agent can use. A rule whose values are words MUST carry it, because it is the list a closer layer narrows. A rule whose default is a number is a ceiling, and its default is the highest value any layer may set. A rule whose default is true or false needs no list. On a preference allowed is OPTIONAL, and where it is absent any value of the default's type may be sent, which the agent still uses exactly or refuses. job_may_set is true when a sender who does not own the agent may set the setting for a job, and an absent job_may_set is read as false.

A setting named model is the AI model the agent's work calls, so an organization's rule about which models may be used narrows that setting's allowed. tested_models lists the models the author has tested the agent with. It SHOULD be a subset of the model setting's allowed, and a model that is allowed and not listed is permitted and untested, which a reader is told (Section 9.5). named lists the author's named run configs. Each has a name, unique in the block; settings, giving values only to declared settings, each inside its setting's allowed or under its ceiling; and digest, computed as Section 5.8 says over the entry without digest. replay, OPTIONAL, is true when the agent can replay a saved run's step without calling a model, so a pin move can be checked by comparing outputs (Section 5.8, Moving a pin); absent means it cannot.

A declared setting is a choice made for each job, so it MUST NOT be a credential, a key, an address or an account identifier. What an install binds is an install setting, named in the install file (Section 12.4), and is never declared here. A run config that an owner, an organization or a person saves is kept with them and is never added to the Descriptor, which differs from its package's draft only as Section 12.6 rule 6 allows. An agent whose Descriptor has no run_config member takes no settings.

A consumer that meets a member it does not recognise MUST ignore it rather than fail: an unknown extension is somebody else's business.

6.3 Kinds#

An input or output kind is a media type where the thing is a file: application/pdf, application/gzip, text/csv. Not every input is a file, so four value kinds sit beside the media types:

Kind Means
text A string a person or program supplies inline.
identifier A name for a thing: an agent handle, a record id, a subject key.
url An address to be used as an address.
document A fetchable file whose media type is not fixed.

A non-file input MUST use a value kind. Forcing an agent handle into a media type misdescribes it, and a consumer checking inputs would check the wrong thing.

6.4 The rules#

  1. Every fact has one authored spelling. A fact appears in the Descriptor once. Any other document carries a projection or a reference (Sections 6.1 and 6.8).
  2. An absent member means not stated. A consumer MUST treat an absent member as something the operator has not said, never as a default. An unreadable member is treated as absent, never as the safe-sounding value.
  3. It carries shapes only. Media types, region names, and system names belong in a Descriptor. Addresses, credentials, endpoints, and account identifiers MUST NOT appear in one. A document violating this does not conform, whoever wrote it.
  4. Evidence stays outside it. Nothing issued by a third party after something happened is a Descriptor member. A Descriptor states; records and verdicts check.

6.5 Versioning and the digest#

A Descriptor is standing: true until its operator changes it. It is versioned by replacement. There is no partial edit; a new version is a whole new document.

The digest is over the exact bytes served, with no canonicalization. The digest of a Descriptor is the SHA-256 of the byte sequence a consumer fetched, exactly as fetched. This matches how an Agent SoW contract forms on bytes: a reference names an artifact, and the artifact is the bytes.

A reference to a Descriptor carries its digest, and MAY carry a location. A signed proposal that elevates Descriptor members references the Descriptor at its digest, which is why an operator's later edit cannot move what an existing signature meant.

agent_version orders versions of the agent, not edits of the document. Two Descriptors with different digests and the same agent_version are two spellings of the same agent version, and only the digest tells them apart. A Descriptor describing a changed agent MUST carry a new agent_version.

6.6 The signature#

A bound Descriptor SHOULD carry the operator's signature, made with the subject's identity key, so a copy stays checkable wherever it travels. A bound Descriptor without one is trusted only as far as the place it was fetched from.

The signature follows the family convention (Section 8.1). The tag defined here:

  • descriptor-statement-v1: the operator's statement that this is the subject's standing description. by MUST be the subject's own key, the same key as subject.id.

The digest (Section 6.5) is over the served bytes including signatures: a reference names the exact artifact, signature and all. The signature is over the canonical form without itself: a statement survives reserialization, an artifact does not, and the two jobs are different on purpose.

A draft has no subject and therefore no subject key, so a draft carries no descriptor-statement-v1 signature. Whoever passes a draft around vouches for it themselves.

6.7 Serving and discovery#

The addresses. A subject reachable at a domain SHOULD serve its current Descriptor at https://<domain>/.well-known/agent-descriptor.json, beside the A2A card and the AgentDoc. Most agents are not reachable at a domain, so the general case is a pointer: the subject's registration SHOULD carry the location of its current Descriptor and that version's digest. A consumer who has found the agent has found its Descriptor.

The registry. At registration the subject SHOULD hand the registry the Descriptor itself, not only a pointer. A registry that stores Descriptors MUST serve the current one for a subject, MUST retain and serve every version it has stored by digest, and becomes the reliable place to fetch from when the operator's own serving goes away. Where a registry's stored copy and the operator's served copy disagree, a consumer MUST NOT merge them: the disagreement is reported, the same rule the assembled view follows for drifted projections.

Asking the agent. A subject SHOULD answer a request for its own current Descriptor, before any agreement exists, answering with the document bytes and their digest. This is entryway exchange 2 (Section 4.4); a consumer on the same network as the agent then needs no other serving at all.

History. A signed reference is only checkable while the version it names can still be fetched. Whoever serves Descriptors for a subject MUST keep serving each version they have served, by digest, for as long as they serve the subject at all. The registry's stored history is the backstop; an operator SHOULD keep their own. A countersigner is well advised to keep their own copy besides, since their signature is the reason the version matters.

Hosted agents. Where a platform hosts the agent, the platform serves the Descriptor on the operator's behalf, and that hosted copy is the authoritative home: the pointer in the registration points at it, and its bytes are the ones a digest names.

Knowing it changed. Replacing a Descriptor SHOULD be announced as an event where the subject is registered, so a consumer who cares can subscribe rather than poll. A consumer without the event compares digests on refetch. Staleness is detectable either way; the event only makes it cheap.

6.8 Projections and consumers#

Four documents consume the Descriptor, each in its own way, and none of them edits its copy:

  • The A2A card is generated from it: does becomes the description, offerings become skills, and kinds coarsen to input and output modes. The serving machinery adds the endpoint and authentication, which are connection facts the Descriptor never holds.
  • The registration manifest carries the pointer and digest and projects acts_for, interaction, fleet and each offering's scope where it has fields for them.
  • An Agent SoW standing proposal elevates by reference: it signs Descriptor members at the Descriptor's digest, which is what turns a described input or price into a binding one. It does not restate them.
  • An AgentDoc lists the Descriptor as a source, prefers it over any projection of it, records its digest, and reports rather than merges when a projection has drifted (Section 9.4).

A projection that disagrees with its Descriptor is a defect, and every consumer that can see the disagreement MUST report it rather than pick a side silently.

Checking a Descriptor is mechanical: the three required members are present, a bound document carries acts_for with one of its three values, format names this specification, every kind is a media type or a defined value kind, every offering's scope and the members it requires pass Section 6.11's checks, no document written under this version carries shape, no member carries an address, credential, or endpoint, a bound document's signature verifies against subject.id, and a draft carries no subject and no subject signature. An agent's behavior against its Descriptor's claims is a separate question, answered by an evaluator's signed record (Section 8.4), and never by this document about itself.

6.9 The wider declaration set#

The declarations below are what a well-described agent states about itself beyond the Descriptor's core members. Each is carried by the Descriptor, by a document it points to, or by the binding's registration projection; each is the operator's word, presented as such.

Standing. One defined value: guest. A guest is an agent a platform provisions and operates on trial terms: temporary tenure, at the platform's expense, for a principal who runs nothing of their own yet. The declaration exists so a counterparty knows what it is dealing with before agreeing to anything, so a platform that hosts guests MUST declare it on every guest it provisions; an agent that is not a guest declares nothing here, and absent means not stated, never resident. Four obligations follow from the declaration, wherever it appears. A guest MUST run under an allowance (Section 7.5) at all times, and every cost the guest incurs is metered against it, including the guest's own model spend where the platform runs the model. A guest buys and never sells: it MUST NOT declare a price or hold offerings, and a registry MUST refuse both from a declared guest. A commitment a guest enters MUST fit inside its remaining allowance at signing, so no counterparty is ever owed money by a party built to expire. And a guest past its tenure refuses mechanically (Sections 4.6 and 4.7), stating that it has lapsed, rather than going silent. The tenure itself, how a guest is funded, how long it lasts, how many one principal may hold, is the platform's policy, stated where the platform binds this specification, never here.

Interaction, the caller's side. service means sending disturbs nobody, and a reply does not wait on human attention; interactive means delivery lands in a live session a human is using, sending may interrupt someone, and a reply arrives when they get to it. Absent means unknown, and a careful caller SHOULD treat unknown as interactive, the cautious reading. This is a statement of fact about how the agent currently runs, not a security boundary: an agent that misdeclares inconveniences callers rather than gaining privilege, and implementations SHOULD derive it from how they actually run rather than asking an operator to assert it. It answers only whether a person is attending the agent right now. Whom the agent acts for is the next declaration, and a caller MUST NOT read one from the other.

Acting for, the caller's side. acts_for (Section 6.2) is what the consent rules read, because each of them protects a particular principal and has to know whether there is one.

  • The door. A connection (Section 7.1) is between two people's agents, so an implementation MUST NOT offer a connection from an agent that does not declare person, and MUST NOT offer one to an agent whose Descriptor declares organization or anyone. Where the other agent's acts_for is not stated, the person deciding is shown that it is not stated before they offer or accept, and the choice is theirs. The owner who reviews held senders and says yes to an order is, for an agent that acts for a person, that person, and for one that acts for an organization, whoever the organization names.
  • Grants. The grants of a connection, and a business's PACT grant (Section 7.8), are permission a person gave. Only an agent that declares person acts on them for a person. A business's agent that serves personal agents through a PACT Provider declares organization. An agent that declares anyone holds no grant from anybody and acts on no one's account.
  • Messages for a person. Agent Messaging lets a sender mark a message for the person behind the receiving agent (Agent Messaging, Section 5.7). That person is, for an agent that declares person, its owner; for one that declares organization, whoever the organization names to read such messages; and an agent that declares anyone has no person behind it, so a message marked for a person has no reader there and the agent MUST NOT say that it keeps those rules. A sender that finds acts_for not stated relies on the receiver's own declaration of those rules, as Agent Messaging already requires.

Modes. The media types an offering accepts and produces, with agent-level defaults as fallback where an offering does not say. Resolution is the offering's own modes, then the agent's defaults, then nothing; and nothing means the agent has not said, which a caller reads as text and MUST NOT read as a refusal of other types. Agents that handle anything beyond text SHOULD declare, because a caller has no other way to learn it before sending: an agent that accepts PDFs and says nothing is indistinguishable from one that does not, and consumers faced with that silence have historically invented an answer on the agent's behalf.

Needs and delivers. What must be in hand before work can start, and what the caller gets. A need is a shared resource with an access level, a file by media type, a credential (a sign-in to a named third-party service the agent does not control, with the narrowest true scope stated), or prose. Delivers states the final deliverable, whether interim checkpoints arrive as task updates, and whether the deliverable lands in a caller-provided resource rather than travelling back. Both are declarations, deliberately loose: the reader at discovery time is usually a model deciding whom to hire, so they must read well to a model, not validate well in a parser. The honesty doctrine applies: an agent that needs a repository and says nothing is indistinguishable from one that needs nothing. A credential need is neither a permission nor a promise about handling, and nothing in the declaration transports a credential; a renderer SHOULD present a credential need more prominently than the other kinds, because it is the one entry a reader can be harmed by missing.

Reporting level. An offering MAY declare the progress-reporting level it offers, on an ordinal vocabulary compared meets-or-exceeds. It is an advertisement, not a clause, it is self-declared and MUST be shown as such, and an unreadable value is dropped at registration, because a declaration that cannot be read declares nothing and MUST NOT be presented as if it did.

Sealing posture. A declared encryption key (Section 7.2) says an agent can be sealed to; the sealing posture says whether anyone should, and what happens to a request that arrives in the clear. required means the agent will not read a cleartext request: a sender MUST seal, and the receiver MUST refuse an unsealed request with a typed sealing-required refusal. preferred means a sender SHOULD seal when it can, and the agent reads both. Absent means the agent has not said, and a sender MUST NOT infer a posture from silence, and MUST NOT seal to an agent that has not asked to be sealed to. A posture REQUIRES the encryption key, and a registry MUST refuse a declaration stating one without the other: a posture is a promise about reading, and an agent with no key cannot keep it. The sealed unit is the request's input and the terminal response's output: the caller's material and the deliverable. Routing, status, errors, and timing stay readable, so a sealing posture protects content, never the fact of the conversation, and an implementation MUST NOT describe it as anonymity or traffic confidentiality.

Data use. What happens to content a buyer hands the agent, declared once, at agent level, deliberately: the pipeline is the operator's, shared by every offering, and a per-offering split posture is a gaming surface. Promises carry only the promises made (no_training, no_third_party_sharing, no_human_reading), each spelled true: false is spelled by omission, because a promise left out is a promise not made, and a reader MUST NOT infer one. Retention states the ceiling in days the operator is prepared to bind. Memory, beside it, says whether what a job was given or learned is kept for later jobs: remembers-across-jobs when it is, and starts-clean-each-job when every job begins with nothing from an earlier one. Absent states nothing, and a reader MUST NOT read silence as a clean start. Processors name the services content passes through, including the model services the agent calls, which is what lets an agent built on an upstream model API make the no-third-party-sharing promise honestly instead of staying silent or lying; an empty processor list is a statement, an omitted one states nothing. Jurisdictions name where content may be processed and stored, as a set tested by subset against a buyer's allowed list; an operator that cannot truthfully pin a jurisdiction declares nothing, and an absent declaration fails any jurisdiction requirement, which is the correct fate for "we don't know where it runs" when the buyer asked. Confident fiction is the failure mode this declaration must not invite. Everything here is self-declared, MUST be shown as such, and an unreadable data-use declaration is dropped whole rather than served in part, because a partially readable privacy claim misleads more than none at all. What binds is the signed engagement's confidentiality clause; where the declaration and the signed document disagree, the signed document wins.

Compliance. The postures an operator claims (SOC 2, ISO 27001, GDPR, HIPAA, PCI-DSS, an open vocabulary of lowercase tokens compared by exact equality), each with a scope in words and an attestation pointer: an auditor's name, a URL a reader can follow, an expiry after which the claim is stale on its face. Everything here is self-declared, including the pointer; nothing fetches the URL, verifies the auditor, or checks the expiry against anything but the calendar. Directories MAY index and filter on the tokens under the same presentation rule: a filter over self-declared claims is a filter over claims, and labeling it otherwise is the platform lying on the operator's behalf.

Access. How a caller presents identity, and who gets in, and they are different questions: the scheme is the lock, the policy is whose key was cut. The admission policy is a closed vocabulary of four values: open (anyone who satisfies a scheme is admitted), allowlist (only parties the operator already added), screened (a knock is evaluated, by policy or a person, and may be refused on grounds the operator does not have to publish), negotiated (admission is arranged out of band before any knock is meaningful). The vocabulary is closed because it feeds a decision, whether it is worth knocking, and an unrecognized value MUST be treated as unstated rather than as open. A scheme over the http transport is also the one statement that an agent on a mesh can be reached from outside it: a platform that brokers outside callers to its agents through a gateway MAY define a scheme for that gateway (a key the caller presents there), and an agent whose registration carries it has been opened to outside callers by its operator, while an agent without it is reachable on its mesh only and its projections (Section 6.8) MUST name no outside endpoint. The choice is the operator's, is made where the agent's door is enforced, and is projected into the declaration rather than typed into it. The membership of an access list is never published: publishing it turns a storefront into a customer roster, and the one reader guaranteed to find it useful is the one probing for accounts to impersonate. Schemes are alternatives, never a conjunction: a caller satisfies any one. Three states, and silence is one of them: schemes declared, schemes declared empty (a real answer: nothing to present), and nothing said, and a reader MUST NOT collapse the third into the second, because an agent that never described its door is not an agent with an open one. Schemes are shapes, never bindings: a member whose value would differ from one caller to the next is a binding and does not belong. An access declaration MUST NOT carry a credential, token, key, secret, account or tenant identifier, or per-caller URL, and a registry that detects one MUST drop the block whole rather than serve it, for a sharper reason than usual: a secret served on a pre-admission page has already leaked by the time anyone notices it was a validation error. Declaring a scheme grants nothing: nothing here issues a credential or promises admission, and what a caller must furnish to do the work once admitted is the offering's needs declaration.

6.10 The declaration doctrine#

Three rules bind every consumer of any declaration:

  1. Absent means not stated. Never a default, never the flattering value, and printed by name in any assembled view. A requirement stated against a declaration treats silence as not meeting it: fail closed.
  2. Shapes, never bindings. Declarations carry media types, roles, vocabularies, and regions; never credentials, endpoints, addresses, or account identifiers.
  3. Declared is a strength, not a verdict. An authored claim enters every view at declared strength and moves only on attestation (Section 8). No consumer may render a self-declaration as verified or enforced.

6.11 Scope and authority#

Before this version every offering was named work with typed inputs and outputs, and a reader could check a request against an offering by its inputs alone. Some agents take an instruction in words instead: change this repository, look into this question, tidy these files. This section lets such an agent say so plainly. It keeps the rule of Section 4.6, under which there is no default route, and it keeps a reader from taking an agent that will try anything for one that can do anything.

Scope. scope on an offering is one of three values:

Value What the offering may be asked What it MUST declare
task-specific The named work its description gives, with the inputs and outputs it declares. Its inputs and outputs (Section 6.2).
open-with-focus Any instruction within a stated focus. focus, workspace, authority, its deliverables in outputs[], and ceilings.
open-ended Any instruction. authority and ceilings, and the agent declares its data use (Section 6.9) with retention, processors and memory. It makes no claim about what it can do.

An offering without scope is task-specific. Absence has a defined meaning here, unlike almost every other member (Section 6.4, rule 2), because task-specific is what every offering declared before this version meant, so every existing Descriptor stays valid and means what it meant. A scope the reader does not recognise is read as open-ended, the reading that claims least about what the offering can do.

Scope is declared on each offering and nowhere else. One agent MAY carry offerings of every scope. Wherever the agent's scope is summarized, on a card, in a listing or in an AgentDoc, the summary is derived from its offerings by listing the scopes they carry, and a Descriptor MUST NOT carry an agent-level scope, which would be a second spelling of those facts (Section 6.4, rule 1).

An open offering receives its instruction as an input of kind text that it declares like any other, so Section 4.7.1 applies to it unchanged.

Focus. focus on an open-with-focus offering is one word from a closed vocabulary:

Value The instructions it takes
software Work on code, its tests, and the tools that build and run it.
documents Writing, editing, checking and arranging documents.
data Collecting, cleaning, analysing and reporting on data.
research Finding and weighing sources, and reporting what they say.
operations Running and tending systems and routine business processes.

The offering SHOULD also carry role, a role of the Agent Roles registry named by its standard offering name, because a role is a contract with refusals a reader can check, while a focus word only says where the instructions lie. The offering's one-sentence description says in words what the focus covers. A focus the reader does not recognise is read as not stated, and an open-with-focus offering without a readable focus is read as open-ended.

Workspace. workspace[] names the shared resources (Section 5.3) the offering works in, as shapes. Each entry carries kind, the resource kind a request's resource entry names (an open vocabulary, in which Agent Messaging reserves git); access, read or read-write; and for, a sentence saying what the work does there. An entry MAY instead name a standing system with system, a name from systems[], whose access is the one declared there. A workspace never carries an address (Section 6.4, rule 3): the address of the repository or folder arrives with each request. An empty workspace is a statement: the offering works only on what a request sends it and returns.

Authority. authority lists what an offering can touch beyond the inputs it is sent and the outputs it returns, from this closed list:

Value The offering can Builds on
reads-files Read files and resources in its workspace. A resource's read access (Section 5.3).
writes-files Create, change and delete files and resources in its workspace. A resource's read-write access (Section 5.3).
reads-systems Read a standing system. systems[] access read.
updates-systems Change the records a standing system holds. systems[] access write.
triggers-systems Set off an action in a standing system. systems[] access trigger.
runs-commands Run programs on its host or in its workspace. Nothing earlier: the members above say what is reached and never what is run.
reaches-network Fetch from, or send to, network addresses that no declared system or workspace entry names. Nothing earlier: a declared system is reached by its name, and this value covers everything else.
sends-messages Send messages to parties other than the requester. The connection grants messages, share and scheduling (Section 7.1).
spends-money Commit money on the requester's or its owner's behalf. The connection grant errands (Section 7.1), the budget (Section 5.4) and the allowance (Section 7.5).

An empty list is a statement: the offering touches nothing beyond its inputs and outputs. An absent authority on a task-specific offering states nothing, and a reader MUST NOT read it as empty. A value outside the list makes the whole list unreadable: a registry MUST refuse the declaration, and a reader that meets one reads the offering's authority as not stated and MUST NOT keep the values it did recognise, because a list read in part could hide the one value that mattered. reads-systems, updates-systems and triggers-systems each require a systems[] entry at the matching access, and a Descriptor that declares one without the other does not conform.

authority_decided_by on the offering says what keeps a running job inside its authority: rule when the runtime stops the job from touching anything the list leaves out, and model when the model is told the list and asked to keep to it. Absent, it is not stated.

Ceilings. ceilings on an offering bounds one job. Each member is { "most": <value>, "decided_by": "rule" | "model" }, where rule means the agent's node or runtime stops the job at the value and model means the model is told the value and asked to keep to it:

Member The most
job_seconds Seconds one job runs.
cost_per_job One job costs the requester, as money in integer micro-units of an ISO 4217 currency (Section 7.6).
spend_per_job One job may commit on the requester's behalf, as money. REQUIRED where authority includes spends-money.
messages_per_job Messages one job sends to parties other than the requester. REQUIRED where authority includes sends-messages.

An open offering MUST carry job_seconds and cost_per_job. A ceiling without decided_by is not stated as to what applies it, and a renderer MUST NOT present it as enforced. Where a request carries a budget (Section 5.4), the tighter of the budget and cost_per_job decides. An install MAY lower an offering's ceilings and MUST NOT raise them (Section 12.6, rule 6).

{
  "id": "change-a-repository",
  "name": "Change a repository",
  "description": "Makes the change an instruction asks for in one code repository and opens it for review.",
  "scope": "open-with-focus",
  "focus": "software",
  "role": "role-code-writer",
  "inputs": [ { "name": "instruction", "kind": "text", "required": true } ],
  "outputs": [
    { "name": "change", "kind": "identifier", "when": "per_task" },
    { "name": "summary", "kind": "text/markdown", "when": "per_task" }
  ],
  "workspace": [ { "kind": "git", "access": "read-write", "for": "the repository the change is made in, on a branch of its own" } ],
  "authority": ["reads-files", "writes-files", "runs-commands"],
  "authority_decided_by": "rule",
  "ceilings": {
    "job_seconds": { "most": 3600, "decided_by": "rule" },
    "cost_per_job": { "most": { "amount_micro": 20000000, "currency": "USD" }, "decided_by": "rule" }
  }
}

At the boundary. A request to an offering that declares a workspace or an authority MAY carry authority, the values from the offering's list that the requester allows for this job; the job then runs under that narrower list, and a request without it allows the offering's whole declared list. A request whose allowed authority includes spends-money MUST carry spend_limit, the most the job may commit, as money. The boundary checks, by rule and before anything that thinks sees the request, in the order of Section 4.6: that every resource the request hands over has a kind a workspace entry names and an access no wider than that entry's; that every value in the request's authority is one the offering declares; and that a required spend_limit is present and no higher than the offering's spend_per_job. A request that arrives through a connection and allows spends-money is an order, and it needs the errands grant and its owner's yes as Section 7.1 says. These checks apply to every offering that declares the member checked, whatever its scope.

The refusal is SCOPE_REFUSED. It carries message, a passage for a person; decided_by; offering; reason, one of workspace, authority, spend_limit and focus; and allowed, the workspace entries or authority values the offering declares, where the reason has a list. workspace, authority and spend_limit are decided by rule. focus is decided by the model, always: it is the answer of an open offering whose model judged that an instruction falls outside its focus, and it is given after the boundary's checks have passed.

Testing, by scope. Each scope is tested in the way its claim can be tested, and an evaluation record (Section 8.4) says which way it used.

  • A task-specific offering is tested case by case, as before this version: each case asks for the named work and checks what comes back against the declared inputs and outputs.
  • An open-with-focus offering is tested against an evaluation set for its focus: a published, versioned set of instructions within that focus, with the checks each result must pass. A signed evaluation record names the set by name, version and digest, and carries the result. One focus may have many sets, and a reader compares results only between records that name the same set.
  • An open-ended offering is tested only on its limits: cases that probe its ceilings, its authority, its workspace and its data-use promises. An evaluation record MUST NOT carry a capability case for an open-ended offering, and a reader MUST NOT read a pass on its limits as a statement about what it can do.

Every refusal case checks decided_by as well as the reason: a refusal the boundary owes is decided by rule, and one marked rule that a model made fails.

Directories. A directory, a matchmaker, or anything else that searches Descriptors MUST NOT return an open-ended offering as a match for a search by the work wanted, because the offering makes no claim about what work it can do. It MAY list one where a searcher asks for open-ended offerings by scope, or filters by authority, ceilings and data use. An open-with-focus offering MAY be matched by its focus and its role, and a directory that matches it MUST show it as open-with-focus, with its focus, its authority and its ceilings, and MUST NOT present it as able to do any particular piece of work within that focus unless an evaluation record says how it did on a set.

Conformance. A checker verifies these declarations mechanically: every scope, focus and authority value comes from its list; an open-with-focus offering carries focus, workspace, authority, at least one output and ceilings; an open-ended offering carries authority and ceilings and its agent declares data use with retention, processors and memory; every open offering's ceilings include job_seconds and cost_per_job; spend_per_job and messages_per_job are present where the authority needs them; a systems value is backed by a system at the matching access; and no Descriptor carries an agent-level scope. Five cases prove an agent applies them at its boundary, run against every offering that declares a workspace or an authority: a request naming an undeclared offering, refused not-found by rule; a resource of a kind the workspace does not name, refused with reason: workspace; a request allowing an authority value the offering does not declare, refused with reason: authority; a request allowing spends-money with no spend_limit, refused with reason: spend_limit; and a request inside every bound, admitted. Each refusal arrives before any work and carries decided_by: rule. The fixture offering-scope.json, in this specification's conformance folder, pins these cases, the mapping of Section 6.12, and the directory rule.

6.12 Retiring shape#

Until 0.27.0-draft a Descriptor could carry shape, which described the agent's inside: what it runs on, which model it calls, whether its steps are fixed, whether it remembers, whether its tools are fixed, and what kind of thing it is. This specification describes an agent from the outside. Each of those facts either answers a question a caller can rely on, and that question now has a member of its own, or it does not, and it leaves the Descriptor. shape is taken apart over one version.

Former member Where it goes How a reader of an older Descriptor reads it
kind Removed. Its real question, whether code or a model decides, is answered by decided_by on each refusal and limit (Sections 4.7 and 6.11). What was installed MAY still be said, as background, in a deployment record's installed (Section 8.3). Ignored.
memory Data use, beside retention (Section 6.9). keeps as remembers-across-jobs, and starts_clean as starts-clean-each-job, carried as the operator's word with the Descriptor as its source.
model Data use processors (Section 6.9). The value as one processor, carried as the operator's word with the Descriptor as its source.
steps scope on each offering (Section 6.11). Mapped to no scope. Scope is declared offering by offering, and steps said how the agent worked rather than what it may be asked, so each offering keeps the scope it declares, which is task-specific when it declares none.
tools_runtime authority on each offering (Section 6.11). Mapped to no authority, for the same reason: neither value said what the tools touch. An offering that declares no authority has none stated.
fleet fleet, a member at the level of the agent's identity (Section 6.2). As fleet.
harness Deployment records only, in target (Section 8.3). Ignored. A Descriptor names no harness.

For this revision, readers accept the old members and map them as the table says, and writers emit the members that replace them and never shape. Where a Descriptor carries both a former member and its replacement, the replacement governs and the former member is ignored. The old members are removed in 0.28.0-draft: a reader of that version treats shape as an unknown member and ignores it (Section 6.2). The trial declaration's shape (Section 7.7) and the build record's shape (Section 8.2) are different members with the same name, and neither changes.

The AgentDoc is assembled from an agent's Descriptor and the records others sign about it. It is Section 9 of the specification and has a site of its own at agentdoc.net.