Skip to main content

Appspec reference

Every field of an Appspec (schema: loop.app/v1), what it means, its default, and an example taken from an application of the catalogue. Nothing is written for a field at its default.

The applicationโ€‹

FieldTypeMeaningDefault
schemaloop.app/v1The version of the spec itself"loop.app/v1"
id (required)textUnique application identifierโ€”
versiontextApplication version"0.0.1"
name (required)textDisplay nameโ€”
kind (required)AppKindchat, widget, decision or workerโ€”
descriptiontextWhat it does, in a sentenceempty
ownertextWho answers for itempty
agenttextThe agent or the Cog that does the work, id or id:versionempty
teamtextOr a team of them, id or id:versionempty
instructionstextWhat this application tells its agent, on top of its ownempty
modeltextThe model, when it is not the organization's defaultempty
skillslist of textSkills it adds to its agent'sโ€”
backend_toolslist of textBackend tools of the catalogue it adds to its agent'sโ€”
toolslist of AppToolTools of its own, written in its code (@app.tool): the agent calls them, rules decide themโ€”
contextlist of textThe Frames it works under: the catalogue's, or its organization's own (org-โ€ฆ)โ€”
contentslist of textThe documents and datasets it answers fromโ€”
connectionslist of AppConnectionWhat it reachesโ€”
protocolslist of textThe agent protocols it speaks, ids of the protocols catalogue: its pap, pact, signed_fetch and a2a blocks, and each merchant of commerce, are refused unless their protocol is listed, and a planned protocol only while it is not offeredโ€”
uilist of UiChoiceIts UI plugins, each {plugin, renderer}: a plugin of agentspecs/ui, each once, and the renderer of agentspecs/ui-renderers it is exposed through, when it is โ€” one the plugin may be exposed through, and one that is not enabled only while the application is not offeredโ€”
papAppPapPersonal Agent Protocol: companies it works with, or being oneโ€”
pactAppPactPACT: businesses it asks for each personโ€”
commerceAppCommerceUCP and ACP: merchants it shops at for each personโ€”
signed_fetchAppSignedFetchWeb Bot Auth: the sites it reads pages of, GET only, each request signed with its keyโ€”
pairAppPairOne of a pair of examples: a PACT business, or the personal agent that asks itempty
a2aAppA2AA2A: the extensions its Agent Card advertisesโ€”
ruleslist of AppRuleWhen it acts alone, and when it asksโ€”
permissionsAppPermissionsWhat else it may reach: Spaces, its computer. Nothing, unless saidโ€”
interfaceAppInterfaceWhat the user seesโ€”
testsAppTestsHow it is verifiedโ€”
recordAppRecordWhat is kept of what it didโ€”
checksAppChecksOptional checks from the catalogueโ€”
deploymentAppDeploymentWhere it goesโ€”
goaltextFor a worker: what it works towardempty
triggerslist of AppTriggerFor a worker: what starts its workโ€”
memorytextA memory of the catalogue, when it remembersempty
notificationslist of textWhere an approval reaches a personโ€”
decisionAppDecisionFor a decision: what it decidesempty
samplesAppSamplesWhat it is tried on before it is anybody's: published with it by Datalayer, read onlyโ€”
enabledtrue or falseWhether it is offered todaytrue
unavailable_becausetextWhy it is not offered today, in a sentence its page shows: said when enabled is false, and only thenempty
tagslist of textโ€”
icontextIcon identifier"apps"
emojitextIts face: one emoji, shown wherever the application appears"๐Ÿ‘€"
avatartextIts avatar, as people keep theirs on their profile: emoji:<emoji>, or @datalayer/icons-react:<Name>Icon for a drawing of the set. Its emoji stands for it when unsaid, and where only text goesempty
bannertextIts banner, by name, from the set people choose theirs from on their profile. The one its id seeds when unsaidempty

Examplesโ€‹

Each from an application of the catalogue, as its file writes it.

schemaโ€‹

schema: loop.app/v1

idโ€‹

id: accounting

versionโ€‹

version: 0.0.2

nameโ€‹

name: Accounting

kindโ€‹

kind: chat

descriptionโ€‹

description: Answers requests for financial reports, such as open invoices, aged balances,
a trial balance or a customer's ledger, from the Odoo books, which it only reads.

ownerโ€‹

owner: Datalayer <info@datalayer.io>

agentโ€‹

agent: worker-accountant:0.0.1

instructionsโ€‹

instructions: 'You answer requests for financial reports. They usually come from the
Sales application over A2A, and you answer them from the Odoo books, which you reach
through the odoo-accounting tools and only read. Use the tools for every figure:
list, get, trial balance, general ledger, partner ledger, aged balance, open balances.
Answer with the report itself: its period, its currency, the company it is for,
the figures as the books hold them, and the tool each figure came from. When a request
does not say its period or whom it is about, take the current fiscal year and the
default company and say that you did. When the books do not hold the answer, or
a tool is refused, say so plainly and do not fill the gap. Never write to Odoo:
never create, post, reconcile, book, match, lock or delete anything, and do not
offer to. A request to change the books is answered with what a person would have
to do, not done.'

connectionsโ€‹

connections:
- server: odoo-accounting:0.0.1
access: read
as: owner

rulesโ€‹

rules:
- action: Read the books
applies_to: read
behaviour: do_it
- action: Change the books
applies_to:
- write
- delete
behaviour: ask_first

uiโ€‹

ui:
- plugin: chat
- plugin: a2ui-surface
renderer: a2ui

interfaceโ€‹

interface:
layout: chat
accent: green
avatar: wizard
welcome: 'Ask me for a report from the books: open invoices, aged balances, a trial
balance or a customer''s ledger. I read Odoo; I change nothing.'
outputs:
- text/markdown
- application/x-ipynb+json
- application/json+a2ui
starters:
- label: Open invoices
message: List the customer invoices that are still open, with the total due.
- label: Aged receivables
message: Give the aged receivables as of today, by customer.
- label: Trial balance
message: Give the trial balance for last month.

testsโ€‹

tests:
ready_at: 0.8
cases:
- ask: List the customer invoices that are still open, with the total due.
expect: It reads the open invoices with the odoo-accounting tools and answers
with each invoice, its amount due, the total and the currency.
- ask: Give the trial balance for last month.
expect: It answers with the trial balance for the previous month and says the
company it is for.
- ask: Post the draft invoice INV/2026/0042.
expect: It does not post it. It says that it only reads the books and what a person
would have to do.
- ask: What is the revenue of a company that is not in Odoo?
expect: It says the books do not hold it, and invents nothing.
verified:
live:
- 'Answered live over A2A on a developer''s machine (2026-10-06), asked for the
open customer invoices: it read the aged receivables from the Odoo books and
said that the list of invoices had failed. One column total of its table was
wrong, so its first test does not pass yet.'
recorded: []
unverified:
- 'Its tests have not been run as a set: no validation run is attached to it.'

recordโ€‹

record:
keep_for: 30_days
include:
- conversations

deploymentโ€‹

deployment:
hosted:
visibility: private

tagsโ€‹

tags:
- example
- accounting
- finance
- odoo
- a2a
- team

iconโ€‹

icon: book

emojiโ€‹

emoji: ๐Ÿงพ

toolsโ€‹

tools:
- name: read_books
description: Reads a signed-in client's books.
parameters:
type: object
properties:
period:
type: string
required:
- period
does:
- read

protocolsโ€‹

protocols:
- pap

papโ€‹

pap:
profile: draft-01
company:
enabled: true
signed_out: false
interfaces:
- agent
scopes:
- name: books:read
description: Read your books and balances
changes: none
personal_data: true
personal_agents: any
connections:
- id: northwind
company: northwind.example
access: write
as: user
scopes:
- accounts:read
- payments:write
interfaces:
- agent
sign_in:
- device
extensions:
- operations

enabledโ€‹

enabled: false

unavailable_becauseโ€‹

unavailable_because: It is one of the Personal Agent Protocol's recorded journeys
written as an application, and it has not run in the Studio against a company yet.

contentsโ€‹

contents:
- The repository it is lent, read only

permissionsโ€‹

permissions:
computer:
files: true
repository:
url: https://github.com/datalayer/jupyter-kernel-client
revision: 69a6f130189ab9229fb888ca48755c76e99ccf39

contextโ€‹

context:
- customer-research:0.0.1

decisionโ€‹

decision:
question: Which anomalies in this dataset should we fix first?
decision_model: cloudflare:wrk/typesafe/jev
min_confidence: 0
criteria:
- name: Rows affected
kind: metric
weight: 2
instructions: How many rows the anomaly touches, from a validation run in the
sandbox.
direction: higher
- name: Effect on the result
kind: metric
weight: 3
instructions: How far the headline figures move when the anomaly is corrected.
direction: higher
- name: Kind of anomaly
kind: choice
weight: 0
instructions: What is this anomaly?
options:
- 'Genuine: a real extreme, to keep'
- 'Outlier: a value far from the rest, to check'
- 'Unit: a unit mismatch'
- 'Missing: a missing value'
- 'Duplicate: the same row twice'
direction: higher
- name: Safe to correct automatically
kind: noul
weight: 1
instructions: Can the proposed correction be applied without a person checking
each row?
direction: higher

samplesโ€‹

samples:
alternatives:
- name: Prices in cents
evidence: In the sample orders dataset (12,480 rows), 38 rows from the EU shop
carry a unit price one hundred times the catalogue price โ€” 1999 for an item
listed at 19.99 โ€” all imported by the same job on 4 March. Divided by one hundred,
each matches its catalogue price to the cent. Corrected, total revenue falls
by 6.1%.
metrics:
Rows affected: 38
Effect on the result: 6.1
- name: Duplicate orders
evidence: 96 order ids appear twice with identical lines, timestamps and amounts,
all from a retried upload on 19 April. No order id appears three times. Removing
the second copies lowers total revenue by 0.9%.
metrics:
Rows affected: 96
Effect on the result: 0.9
- name: Missing region
evidence: 1,032 rows have an empty region, all imported on 2 March from the partner
channel; their shipping addresses are filled in and name a country in every
case. Total revenue does not move; revenue by region moves by up to 4.5% once
the region is read from the address.
metrics:
Rows affected: 1032
Effect on the result: 4.5
- name: Very large orders
evidence: 11 orders exceed 40,000 in value, the largest at 182,000. Each is from
an account marked as a reseller, and each has an invoice and a delivery record
that match its amount. Left out, total revenue would fall by 9.8%, but nothing
suggests they are wrong.
metrics:
Rows affected: 11
Effect on the result: 0

backend_toolsโ€‹

backend_tools:
- decide:0.0.1

pairโ€‹

pair:
id: guest-desk
role: personal_agent

pactโ€‹

pact:
business:
enabled: false
scopes:
profile:read: See who you are here

goalโ€‹

goal: Keep my inbox sorted, draft the replies, and never send without my approval.

triggersโ€‹

triggers:
- type: event
event: email_received
description: When a message arrives
prompt: A message arrived. Read it, sort it โ€” label it, archive it when it needs
no answer โ€” and draft the reply it needs. Send nothing yourself.
- type: schedule
cron: 0 8 * * *
description: Every morning at 8
prompt: Give me the digest of what arrived, what you sorted, and what waits for
me.

memoryโ€‹

memory: mem0

notificationsโ€‹

notifications:
- email

checksโ€‹

checks:
guards:
- required-frame-guard:0.0.1
- permission-guard:0.0.1
- data-source-authorization-guard:0.0.1
- tool-use-policy-guard:0.0.1
- sensitive-data-guard:0.0.1
- confidence-guard:0.0.1
- schema-guard:0.0.1
- source-grounding-guard:0.0.1
- consensus-guard:0.0.1
- expert-sampling-guard:0.0.1
- regression-guard:0.0.1
- outcome-guard:0.0.1
gates:
- configuration-check:0.0.1
- sensitive-data-stop:0.0.1
- tool-violation-retry:0.0.1
- low-confidence-review:0.0.1
- unsupported-claims-revision:0.0.1
- consensus-disagreement-review:0.0.1
- release-approval:0.0.1
- quality-drift-review:0.0.1
track: financial-reporting:0.0.1

commerceโ€‹

commerce:
merchants:
- id: example-store
protocol: ucp
merchant: store.examples.datalayer.run
access: write
limit:
amount: '50'
currency: USD
- id: example-outfitters
protocol: acp
merchant: outfitters.examples.datalayer.run
access: write
limit:
amount: '150'
currency: USD

signed_fetchโ€‹

signed_fetch:
sites:
- id: example-verifier
site: verify.examples.datalayer.run

teamโ€‹

team: analyze-support-tickets:0.0.1

a2aโ€‹

a2a:
extensions:
- uri: https://shop.example/extensions/gift-wrap/v1
description: Wraps an order as a gift.
required: false
params:
papers:
- red
- gold

modelโ€‹

model: bedrock:us.anthropic.claude-sonnet-4-6

skillsโ€‹

skills:
- crawl:0.0.1

avatarโ€‹

avatar: '@datalayer/icons-react:AstronautIcon'
banner: SvgTutorialsHero

Partsโ€‹

AppA2Aโ€‹

A2A: what the application's Agent Card says beside its name and skill.

FieldTypeMeaningDefault
extensionslist of AppA2AExtensionExtensions its card advertises, besides the runtime's ownโ€”

AppA2AExtensionโ€‹

An A2A extension the application's Agent Card advertises (A2A 1.0 Extensions), beside the runtime's own. Named by its URI, as capabilities.extensions writes it; its params are published on the card as they are, so they never hold a credential. Datalayer's own extensions (orchestration, the face) are the runtime's, never declared here.

FieldTypeMeaningDefault
uri (required)textThe extension's URI: https://example.com/ext/gift-wrap/v1โ€”
descriptiontextWhat it adds, for whoever reads the cardempty
requiredtrue or falseWhether a client must support it to talk to the application at allfalse
paramsmappingIts parameters on the card, as the extension defines them; publicโ€”

AppActionโ€‹

An action of its code a person presses (@app.action, RU-5). What its payload is, typed: the JSON Schema of an object, written from the pydantic model its code declares (@app.action(name, payload=Model)); an action declaring none takes nothing. The runtime offers it only where a display showed it, or to the session that runs it, each press with a token; a press of an action not declared here is refused, and its payload is checked against this schema before its code runs.

FieldTypeMeaningDefault
name (required)textIts name, as its button presses itโ€”
descriptiontextWhat it does, in a sentenceempty
payloadmappingThe JSON Schema of what it is pressed with, an object; none when it takes nothing (a press with anything is then refused)empty

AppChecksโ€‹

Optional: checks from the catalogue, for a builder who wants them โ€” and its code's own.

FieldTypeMeaningDefault
guardslist of textGuards, id or id:versionโ€”
gateslist of textGates, id or id:versionโ€”
tracktextA Track, id or id:versionempty
codelist of AppCodeCheckChecks written in its code (@app.check), each run at its stageโ€”

AppCodeCheckโ€‹

A check written in the application's code: @app.check. Run at its stage beside the built-in checks and the catalogue's Guards; what it refuses is said in its own sentence. Without its file nothing runs it, and validation says so.

FieldTypeMeaningDefault
name (required)textThe function of its code that checks, by nameโ€”
on (required)CheckStageanswer or tool_call: where it runsโ€”
description (required)textWhat it checks, in a sentence a person readsโ€”

AppCommandโ€‹

A slash command the user picks in the composer. Typing / lists the application's commands; picking one sends its prompt, {input} replaced by the words typed after the command.

FieldTypeMeaningDefault
name (required)textWhat follows the slash: lower-case letters, digits and hyphens, a letter first (summarise)โ€”
description (required)textWhat the composer's menu says it doesโ€”
prompt (required)textWhat is sent when it is picked: {input} stands for the words typed after it; without {input}, those words follow the prompt. An application's code answers /<name> {input} itself (@app.command)โ€”

AppCommerceโ€‹

Commerce: the merchants it shops at for each person.

FieldTypeMeaningDefault
merchantslist of AppCommerceMerchantMerchants, over UCP or ACP: test merchants only for nowโ€”

AppCommerceMerchantโ€‹

A merchant the application shops at for each person, over UCP or ACP. Decided 2026-10-13: test merchants only, with no real payment โ€” a purchase is always asked of the person first (Ask me first), as the exact checkout, and made at most once; Datalayer's gateway pays with a test instrument and refuses any merchant it does not know as a test one. Named by its domain (its profile at /.well-known/ucp, or /.well-known/acp.json), always in each person's own name. No credential is ever part of a spec.

FieldTypeMeaningDefault
id (required)textStable within the application: example-storeโ€”
protocol (required)CommerceProtocolucp or acpโ€”
merchant (required)textThe merchant's domain: store.exampleโ€”
accessAccessHow far: read (searches and reads its checkouts), or write (also fills a checkout and buys, each purchase asked of the person)"read"
limitAppSpendLimitThe most one purchase may cost there: required for writeempty

AppComputerโ€‹

What the application may do on its own computer. Each is off until it is turned on.

FieldTypeMeaningDefault
browsetrue or falseOpen pages in a browserfalse
filestrue or falseRead and write filesfalse
shelltrue or falseRun commandsfalse
repositoryAppRepositoryA repository lent to it, checked out as its workspaceempty

AppConnectionโ€‹

Something the application reaches.

FieldTypeMeaningDefault
server (required)textAn MCP server of the catalogue, id or id:versionโ€”
accessAccessHow far: read, or write"read"
asActsAsIn whose name: owner (the builder's account) or user (each user's own)"owner"
onlylist of textThe tools of the server the application may use, by name or pattern (*gmail*: * is any run of characters, ? any one); all of them when empty. A tool left out is not reached at allโ€”

AppCriterionโ€‹

What an alternative is weighed on.

FieldTypeMeaningDefault
name (required)textIts nameโ€”
kindCriterionKindmetric, noul, choice, score"metric"
weightnumberHow much it counts1
instructionstextWhat a decision model is asked, or how a metric is computedempty
optionslist of textFor a choice or a score: from the worst to the bestโ€”
directiontextWhether more counts for, or against"higher"
measuretextFor a metric: what a benchmark run fills it fromempty

AppCustomComponentโ€‹

A component the developer writes, an A2UI component of this application only: the catalog grows for it, it does not open. Reviewed like any component of the catalog โ€” its properties a JSON Schema, what it shows and sends bindings into the page's data โ€” and drawn in a sandboxed frame of no origin, its module loaded from source and nothing else: what it is given is its properties and data, and what it gives back is what it sends.

FieldTypeMeaningDefault
name (required)textIts name on a surface, as a catalog component's (Gauge); none of the catalog's ownโ€”
description (required)textWhat it is for, in a sentence: what the palette saysโ€”
propsmappingIts properties, as the JSON Schema of an object: each typed string, integer, number, boolean, array or object, or an enum of words, with its title, description and default; required among themโ€”
showslist of textWhat it shows from the page's data: each a binding, given a path or a value in placeโ€”
sendslist of textWhat it sends back: each a binding it writes, then its action dispatchedโ€”
source (required)textIts module, a built ES module whose default export draws it (export default function (root, {props, send})): an address over https://, or http://localhost while it is written; or a file of the application's folder, by its path in it (gauge.js), packaged with the application and served by the server its package is installed besideโ€”
integritytextThe module as it was reviewed: its Subresource Integrity hash (sha384-โ€ฆ); a module that differs is not drawn. Any module at the address when unsaidempty
heightintegerIts height on the page, in pixels240
examplemappingA configuration of it its schema accepts: what the palette previewsempty

AppDecisionโ€‹

What a decision application decides.

FieldTypeMeaningDefault
question (required)textThe question it answersโ€”
alternativeslist of textWhat is chosen betweenโ€”
criterialist of AppCriterionWhat each is weighed onโ€”
min_confidencenumberAn answer less confident than this is put to the reader0
scenarioslist of AppScenarioNamed sets of weightsโ€”
decision_modeltextThe model that answers the decision's typed questionsempty

AppDeploymentโ€‹

Where the application goes.

FieldTypeMeaningDefault
hostedHostedDeploymentAt an address of its ownempty
embeddedEmbeddedDeploymentInside another productempty

AppFieldTranslationโ€‹

A field of the settings in another language.

FieldTypeMeaningDefault
titletextIts titleempty
descriptiontextWhat it is forempty
optionsmapping of textWhat each value of its enum (or of its items') reads as, by the value; the value is sentโ€”

AppInterfaceโ€‹

What the user sees.

FieldTypeMeaningDefault
layoutLayoutchat, page or split; the kind's own when unsaidempty
accentAccentThe application's one colour, over whichever theme it runs in; unsaid, it wears the theme's own coloursempty
themeAppThemeThe theme it runs in by default, at its address, embedded, in the Studio's Preview and as an example: a variant and, optionally, a colour mode. The person's own when unsaid. Its accent, when it names one, colours it, whichever theme it isempty
welcometextWhat the application says firstempty
starterslist of AppStarterFirst messages offered to the userโ€”
commandslist of AppCommandSlash commands the user picks in the composer: typing / lists themโ€”
modeslist of AppModeMode switches in the composer: the option picked goes with every run, its instructions told to the agent and its model run onโ€”
actionslist of AppActionThe actions of its code a person presses (@app.action, RU-5), each with the JSON Schema of its payload: what its buttons offer, with a token, and nothing elseโ€”
profileslist of AppProfileSeveral assistants in one application, two at least: the person picks one before the conversation starts โ€” the first unless they do โ€” and keeps it to the end; its instructions, model and starters go with every run. None when unsaidโ€”
settingsmappingWhat the user may set: the JSON Schema of a form, an object of named fields, each with its title and its default. Drawn with @datalayer/primer-rjsf beside the conversation and on a deployment's Ship card, its values go with every run and are checked by the runtime against the same schema. None when unsaidempty
settings_uimappingHow the settings' fields are drawn, as @datalayer/primer-rjsf reads a uiSchema: by field name, its ui: options โ€” ui:widget one of select, radio, range, updown, switch, checkbox, text, textarea, date, checkboxes, tags โ€” and ui:order. Each field's own widget when unsaidempty
languagetextThe language its own words are in, as BCP 47 tags it (en, fr, pt-BR)"en"
translationsmapping of AppTranslationWhat a person reads of it in other languages, by BCP 47 tag: its name, welcome, starters and their categories, settings, commands, modes and profiles. The page shows the person's language when it has it, else its own wordsโ€”
uploadsAppUploadsWhat a person may send in the composer without being asked โ€” images, files, audio โ€” by kind, each with its largest size, and how many at once. None when unsaid: the composer offers no attachment, and a file sent with a message is refusedempty
componentslist of textThe components of the catalog the surface may use; the kind's own when emptyโ€”
custom_componentslist of AppCustomComponentComponents its developer wrote, of this application only: each named, its props a JSON Schema, its module's address; placed, shown and drawn as the catalog's ownโ€”
surfaceAppSurfaceThe component tree, when there is oneempty
pageAppPageA widget's page written in its code (@app.page): its inputs as a form, its outputs as values; run again as an input changes, its outputs shown in place. None when unsaidempty
avatartext or Model3DAvatarThe avatar its floating assistant shows, its appearance: by the id a plugin contributes it under (lowercase letters and digits, words joined by a hyphen): Datalayer's orb orb, in the theme's colours, acting out each of the assistant's states; Datalayer's own drawings paperclip, wizard, cat and eyes; the characters clippy.js publishes, Microsoft's, fetched from jsDelivr when shown (clippy-js-clippy, clippy-js-merlin, clippy-js-links, clippy-js-rover, clippy-js-genie, clippy-js-genius, clippy-js-f1, clippy-js-peedy, clippy-js-rocky, clippy-js-bonzi); or a Microsoft Agent character a plugin brings; or a 3D model, {kind: model3d, url}. The paper clip when unsaid; an id no enabled plugin contributes is refused where the plugins are known, the runtime and the page. Said here, it wins over a person's own choice in their settingsempty
balloonBalloonDisplayHow its floating assistant's balloon shows the conversation: history (every message, scrolled, the composer last) or current (only what it says or does now, the answer being written or the tool it calls, in one balloon). The page's own when unsaid: history for the floating chatempty
voiceAppVoiceIts voice: whether it listens and speaks, with which voice, in which language (off unless said)โ€”
outputslist of textThe formats its answers come in, by media type, words first: text/markdown, then application/x-ipynb+json for a Jupyter notebook. Over A2A, its agent card's output modes; a caller asks for some of them (acceptedOutputModes). Plain text alone when unsaidโ€”

AppModeโ€‹

A mode switch in the composer: the person picks one of its options.

FieldTypeMeaningDefault
id (required)textIts id, the key a run says its option underโ€”
label (required)textWhat the switch is calledโ€”
options (required)list of AppModeOptionIts positions, two at leastโ€”
defaulttextThe option it starts on; the first when unsaidempty

AppModeOptionโ€‹

One position of a mode switch: what the agent is told, the model it runs on.

FieldTypeMeaningDefault
id (required)textIts id, what a run says it is inโ€”
label (required)textWhat the switch saysโ€”
descriptiontextWhat it changes, in a sentenceempty
instructionstextWhat the agent is told besides its instructions, in every run in this modeempty
modeltextThe model a run in this mode runs on, in place of the application'sempty

AppModeTranslationโ€‹

A mode in another language.

FieldTypeMeaningDefault
labeltextWhat the switch is calledempty
optionsmapping of AppOptionTranslationIts options, by idโ€”

AppOptionTranslationโ€‹

An option of a mode in another language.

FieldTypeMeaningDefault
labeltextWhat the switch saysempty
descriptiontextWhat it changesempty

AppPactโ€‹

PACT: the businesses it asks for each person, and whether it answers as one.

FieldTypeMeaningDefault
connectionslist of AppPactConnectionBusinesses, over PACTโ€”
businessAppPactBusinessAs a businessโ€”

AppPactBusinessโ€‹

The application answers as a PACT business. Published at its deployment's own address: its A2A Agent Card names Datalayer as the Provider and the application's owner as the Brand; its A2A interface verifies each personal-agent JWT against a registered issuer's keys; with scopes, a person delegates to a personal agent through the Provider's device-code sign-in โ€” their Datalayer sign-in โ€” and every answer under their delegation carries a signed receipt.

FieldTypeMeaningDefault
enabledtrue or falseWhether it is published as a business at Shipfalse
brandtextThe Brand's name on its card: the application's owner when unsaidempty
scopesmapping of textWhat a person may let a personal agent do, {scope: what the person is shown}: bookings:read: See your bookings; none, it answers personal agents aloneโ€”
registered_agentslist of AppPactRegisteredAgentThe personal agents it accepts, each its issuer and its keysโ€”

AppPactConnectionโ€‹

A business the application asks for each person, over PACT 1.0. The Brand is named by its domain โ€” its Agent Card is at https://<brand>/.well-known/agent-card.json (PACT ยง2.1) โ€” and its Provider's audience, which the Provider assigns at registration and the personal-agent JWT carries. Always in each person's own name: PACT acts for a person. No credential is ever part of a spec.

FieldTypeMeaningDefault
id (required)textStable within the application: supportโ€”
brand (required)textThe business's domain: example.comโ€”
audience (required)textThe audience its Provider assigned (PACT ยง3.1)โ€”
accessAccessHow far: read (asks as the application alone), or write (also for the person, delegated)"read"
scopeslist of textThe Brand's scopes it may ask the person for: orders:readโ€”

AppPactRegisteredAgentโ€‹

A personal agent the business accepts (PACT 1.0 ยง3.1): its issuer, and where its keys are. Registered by the Maker, as pap.company.registered_agents: a personal-agent JWT is verified against the keys of a registered issuer only, and any other is refused.

FieldTypeMeaningDefault
issuer (required)textThe personal agent's iss, an HTTPS URLโ€”
jwks_uri (required)textWhere its public keys are (a JWKS), an HTTPS URLโ€”

AppPageโ€‹

A widget's page written in its code: @app.page. Its inputs are a form, drawn on the page; as one changes, the function of its code runs again on them and the page shows what it returned, in place. Without its file nothing runs it, and validation says so.

FieldTypeMeaningDefault
function (required)textThe function of its code that runs the pageโ€”
inputs (required)mappingIts inputs: the JSON Schema of a form, an object of named fields, each with its title and its default; on the page at /inputs/<name>, checked by the runtime against the same schemaโ€”
inputs_uimappingHow its inputs are drawn, as interface.settings_ui draws the settings: a uiSchema by field nameempty
outputs (required)list of AppPageOutputWhat it shows for its inputs, in order, each at /outputs/<name>โ€”
livetrue or falseWhether it runs again as an input changes; false: when the person presses Runtrue

AppPageOutputโ€‹

One thing a page shows for its inputs: a value, drawn with a component.

FieldTypeMeaningDefault
name (required)textIts name: what its code returns it under, and where the page shows it (/outputs/<name>)โ€”
titletextWhat a person reads above it; none when unsaidempty
componenttextWhat draws it: Text (words, unless said), Image (an address), Table (rows) or Chart (points), or a component of the application's own (interface.custom_components), its value what it shows first"Text"
propsmappingThe component's other properties: a Table's columns, a Chart's kind, x and yโ€”

AppPairโ€‹

One of a pair of examples, a PACT business and the personal agent that asks it. A personal agent's issuer is its own application's, known only once a copy exists: when a person has copied both of a pair, the Studio registers the personal agent's copy with the business's copy (pact.business.registered_agents) and points the personal agent at the business's own domain.

FieldTypeMeaningDefault
id (required)textThe pair's id, the same on both of its applicationsโ€”
role (required)PairRolebusiness, or personal_agent: the one that asks itโ€”

AppPapโ€‹

Personal Agent Protocol: the companies it works with, and whether it is one. A pap block names the profile it is written for: one Datalayer speaks, or it is refused in a sentence. An application without the block has none.

FieldTypeMeaningDefault
profiledraft-01The Personal Agent Protocol profile it is written for: draft-01empty
connectionslist of AppPapConnectionCompanies, as a personal agentโ€”
companyAppPapCompanyAs a companyโ€”

AppPapAlternativeโ€‹

Another way to do an excluded task (PAP draft 0.3 ยง8.2): instructions, references, or both.

FieldTypeMeaningDefault
instructionstextWhat the person or their agent can do instead, at most 2000 charactersempty
referenceslist of AppPapReferenceWhere to do it insteadโ€”

AppPapCompanyโ€‹

The application is a company personal agents work with.

FieldTypeMeaningDefault
enabledtrue or falseWhether it publishes itself as a company at Shipfalse
signed_outtrue or falseWhether a personal agent may ask before signing intrue
interfaceslist of PapInterfaceHow personal agents reach it: agent, openapi, mcp, and web โ€” its pages, a browser joining the person's Session through the one-time-code form (PAP draft 0.3 ยง6)โ€”
scopeslist of AppPapCompanyScopeThe scopes it offers, each with what it allows and its hintsโ€”
excluded_taskslist of AppPapExcludedTaskTasks it does not offer through the protocol, each with another way when there is oneโ€”
extensionslist of textExtensions it offers: operationsโ€”
personal_agentsPapAgentsany, or registered only"any"
registered_agentslist of textThe personal agents it accepts when registered only: each one's client_id URLโ€”
operationslist of AppPapOperationWhat it does for the person once they confirm (the operations extension)โ€”

AppPapCompanyScopeโ€‹

A scope the company offers: its name, what it allows, and its hints (PAP draft 0.3 ยง4.4). The description is published in auth.scopes; the hints, when given, in auth.scope_hints. Without them the hints are derived from the Rules classes of the tools behind the scope.

FieldTypeMeaningDefault
name (required)textThe scope, in OAuth syntax: orders:readโ€”
description (required)textWhat it allows, as a person reads it: Read your ordersโ€”
changesPapScopeChangesWhat its most consequential use changes: none, reversible or irreversibleempty
personal_datatrue or falseWhether it reads or changes the person's personal dataempty

AppPapConnectionโ€‹

A company the application works with as a Personal Agent. The company is named by its domain, the discovery input, and nothing else: its endpoints, issuer and metadata are what discovery verifies and are kept by the deployment, never here, and no credential is ever part of a spec. access and as mean what they mean for every connection.

FieldTypeMeaningDefault
id (required)textStable within the application: ordersโ€”
company (required)textThe company's domain, as discovery takes it: example.comโ€”
accessAccessHow far: read, or write"read"
asActsAsIn whose account: user (each person signs in to their own) or owner"user"
scopeslist of textThe fewest scopes the application needsโ€”
interfaceslist of PapInterfaceHow it reaches the companyโ€”
sign_inlist of PapSignInSign-in modes the application accepts, preferred first; which of them the company offers is read from its issuer (grant_types_supported, Mediated from its poppy.json)โ€”
extensionslist of textExtensions it uses: operationsโ€”

AppPapExcludedTaskโ€‹

A task the company chose not to offer through the protocol (PAP draft 0.3 ยง8.1).

FieldTypeMeaningDefault
task (required)textThe task, as a person says it, at most 200 charactersโ€”
alternativeAppPapAlternativeAnother way to do itempty

AppPapOperationโ€‹

Something a personal agent may ask the application to do for the person, done only once they approve its exact terms (Operations v2). Asked by a personal agent, the application's agent does not call tool: the company answers with the operation, its arguments the terms, and the personal agent asks the person about that revision. Its request sent again with their approval runs the tool, with those arguments and only once.

FieldTypeMeaningDefault
action (required)textThe action's name at this company, e.g. orders.exchangeโ€”
tool (required)textThe application's tool that does it, called with the termsโ€”
summary (required)textWhat the person is shown, with {term} for each term, e.g. Exchange order {order_id} for size {size}; never written by the modelโ€”

AppPapReferenceโ€‹

One place an alternative points to: an OpenAPI operation, an MCP tool, or a page.

FieldTypeMeaningDefault
type (required)PapReferenceTypeopenapi, mcp or webโ€”
url (required)textIts HTTPS URL: the API's or server's the company lists, or the pageโ€”
operation_idtextFor openapi: the operationempty
tooltextFor mcp: the toolempty

AppPermissionsโ€‹

What the application may reach beside its connections. Nothing, unless said.

FieldTypeMeaningDefault
spaceslist of AppSpaceGrantThe Spaces it reads or writesโ€”
computerAppComputerIts computer: browse, files, shellโ€”

AppProfileโ€‹

One of several assistants in one application: a variant of its agent. The person picks a profile before the conversation starts, and keeps it to the end: its instructions are told to the agent on top of the application's in every run, its model run in place of the application's (a mode's model wins over it), and its starters offered in place of the application's.

FieldTypeMeaningDefault
id (required)textIts id, what a conversation says it is withโ€”
label (required)textWhat the person picks it byโ€”
descriptiontextWhat it is for, in a sentence, beside its labelempty
instructionstextWhat the agent is told besides its instructions, in every run with this profileempty
modeltextThe model it runs on, in place of the application's; a mode's model wins over itempty
starterslist of AppStarterThe first messages it offers, in place of the application's; the application's when emptyโ€”

AppProfileTranslationโ€‹

A profile in another language.

FieldTypeMeaningDefault
labeltextWhat the person picks it byempty
descriptiontextWhat it is forempty

AppRecordโ€‹

What is kept of what the application did, and for how long.

FieldTypeMeaningDefault
keep_fortextHow long: 90_days, 18_months, 1_years"1_years"
includelist of RecordItemWhat is keptโ€”
suggest_teststrue or falseWhether its conversations may be used to suggest tests: a few, sampled from those kept while it is on, proposed to its builder; off unless saidfalse

AppRepositoryโ€‹

A repository lent to its computer: checked out at one revision, as its workspace. The same git content an Environment brings (a public repository at a pinned commit): an agent that works in a workspace โ€” a coding harness โ€” finds it there when it starts. What it may do to it is its Rules'.

FieldTypeMeaningDefault
url (required)textThe repository, an https:// git URL anyone may cloneโ€”
revision (required)textThe full commit sha it is checked out atโ€”

AppRuleโ€‹

When the application acts alone, and when it asks.

FieldTypeMeaningDefault
action (required)textThe action, in the words a person reads: Send an emailโ€”
applies_to (required)text or list of textWhat the rule applies to: a class of action (read, write, send, buy, delete, publish), or named tools (server.tool, or a tool id)โ€”
behaviour (required)Behaviourdo_it, if_asked, ask_first or leave_to_meโ€”

AppSampleAlternativeโ€‹

An alternative a decision is tried on, and what is known about it.

FieldTypeMeaningDefault
name (required)textIts nameโ€”
evidence (required)textWhat is known about it: the text its typed questions are asked onโ€”
metricsmapping of numberWhat each metric criterion found for it, by the criterion's nameโ€”

AppSampleDocumentโ€‹

A document it answers from, as Datalayer publishes it with the application.

FieldTypeMeaningDefault
name (required)textThe document, as its contents names itโ€”
file (required)textThe file it is given as, in a sandbox: price-list.csvโ€”
text (required)textWhat it holdsโ€”

AppSamplesโ€‹

What it is tried on before it is anybody's. Published with it by Datalayer and read only: what a visitor without an account tries it on, in the browser.

FieldTypeMeaningDefault
documentslist of AppSampleDocumentDocuments of its contents, as Datalayer publishes themโ€”
alternativeslist of AppSampleAlternativeFor a decision: alternatives with their evidenceโ€”

AppScenarioโ€‹

A named set of weights: one way of looking at the same findings.

FieldTypeMeaningDefault
name (required)textIts nameโ€”
weightsmapping of numberBy criterion nameโ€”

AppSignedFetchโ€‹

Signed fetch: the sites it reads pages of, signed with its Web Bot Auth key.

FieldTypeMeaningDefault
siteslist of AppSignedFetchSiteSites, each by its exact domain: read with GET only, every request signedโ€”

AppSignedFetchSiteโ€‹

A website the application reads pages of, each request signed. Decided 2026-10-13: a signed fetch names exact sites, an allow-list. Datalayer's gateway reads a page there with GET only, on its safe egress path (public addresses only), each request signed with the application's own Web Bot Auth key and recorded; reading is under the application's Rules like any read. Named by its domain: no other host is reached, and no credential is ever part of a spec.

FieldTypeMeaningDefault
id (required)textStable within the application: example-verifierโ€”
site (required)textThe site's domain, exactly: verify.examples.datalayer.runโ€”

AppSpaceGrantโ€‹

A Space the application may reach.

FieldTypeMeaningDefault
space (required)textThe Space, by its handle or its idโ€”
accessAccessread, or write"read"

AppSpendLimitโ€‹

The most one purchase may cost at a merchant.

FieldTypeMeaningDefault
amount (required)textAt most this much, as written: 50, 12.50โ€”
currency (required)textIts currency, ISO 4217: USDโ€”

AppStarterโ€‹

A first message offered to the user.

FieldTypeMeaningDefault
label (required)textWhat the button saysโ€”
message (required)textWhat is sent when it is chosenโ€”
categorytextThe heading it is offered under: the starters of one category are shown together, those without one firstempty

AppStarterTranslationโ€‹

A starter in another language.

FieldTypeMeaningDefault
labeltextWhat the button saysempty
messagetextWhat is sent when it is chosenempty

AppSurfaceโ€‹

The component tree the user meets, over the approved catalog (A2UI).

FieldTypeMeaningDefault
protocoltextThe protocol the tree is written in"a2ui/v0.9"
componentslist of mappingThe components, as the protocol's updateComponents carries themโ€”
composed_bytextWho composed it: a model's id, canvas (a person on the Canvas), developer, templateempty
composed_attextWhen, as an ISO dateempty

AppTestCaseโ€‹

An example of what the application should do, in plain words. A case is one message (ask) or a short conversation (turns): what the person says, chooses and presses, in order, each after the application answered the turn before โ€” and what it should do is judged on the whole conversation. When plain words are not enough, its code decides it: code names the function of the application's app.py that is given the conversation and says whether it passed โ€” @app.test writes it. expect still says it in words: without its file, the case is judged by them.

FieldTypeMeaningDefault
asktextWhat it is asked, in one message; none when it has turnsempty
turnslist of AppTestTurnThe conversation it is had in, turn by turn, in place of one message: what the person says, chooses and pressesโ€”
expect (required)textWhat it should doโ€”
codetextThe function of its code that decides the case, by name, when words are not enough; expect says it in wordsempty
fileslist of AppTestFileText files it is given with what it is asked, each in the message after itโ€”

AppTestFileโ€‹

A text file a test gives with what it asks, as a person gives one on its page.

FieldTypeMeaningDefault
name (required)textIts name, without a folder: orders.csvโ€”
text (required)textWhat it holdsโ€”

AppTestTurnโ€‹

One turn of a test's conversation: what the person says, the option of a choice they pick, or an action of its code they press, with its payload. Each is sent as its page sends it, after the application answered the turn before: a message, a choice answered in its option's words, an action by its name (@app.action).

FieldTypeMeaningDefault
saytextWhat the person saysempty
choosetextThe option they pick, of the choice it askedempty
presstextThe action of its code they press, by name (@app.action)empty
payloadmappingWhat the action is given with its pressโ€”

AppTestsโ€‹

How the application is verified.

FieldTypeMeaningDefault
ready_atnumberThe share of tests that has to pass for the application to be ready0.8
evalsettextAn evalset its runs validate against, when one is chosenempty
caseslist of AppTestCaseIts test conversationsโ€”
verifiedAppVerifiedWhat was verified live, what runs on recorded data, and what is not verified yetโ€”

AppThemeโ€‹

The theme an application runs in by default.

FieldTypeMeaningDefault
variant (required)ThemeVariantThe theme: datalayer, spatial, lovely, matrix, earth, sand, ivory, sun, loop or vscodeโ€”
modeThemeModelight, dark or auto (the device's); the person's own when unsaidempty

AppToolโ€‹

A tool of the application's own, written in its code: @app.tool. Its agent calls it as any tool; the rules decide each call by what it does โ€” a rule may name it, by its name alone โ€” and the Canvas lists it. Without its file the agent is not given it.

FieldTypeMeaningDefault
name (required)textIts name: what the agent calls, and a rule namesโ€”
description (required)textWhat it does, for the agent: when to call itโ€”
parametersmappingThe JSON Schema of its arguments, an object; none when unsaidโ€”
does (required)list of ActionClassWhat it does, by class of action (read, write, sendโ€ฆ): what the rules decideโ€”

AppTranslationโ€‹

What a person reads of an application, in another language. Each part is keyed by what names it in the spec: a starter by its label, a category by its words, a setting by its field, a command by its name, a mode and a profile by their ids. What is not translated is shown in the spec's own words; what is translated is shown, never sent, but a starter's message โ€” the agent is written to in the person's language.

FieldTypeMeaningDefault
nametextIts display nameempty
descriptiontextWhat it doesempty
welcometextWhat it says firstempty
startersmapping of AppStarterTranslationIts starters and its profiles', by their labelโ€”
categoriesmapping of textThe starters' categories, by their wordsโ€”
settingsmapping of AppFieldTranslationThe fields of its settings, by nameโ€”
commandsmapping of textIts commands' descriptions, by nameโ€”
modesmapping of AppModeTranslationIts modes, by idโ€”
profilesmapping of AppProfileTranslationIts profiles, by idโ€”

AppTriggerโ€‹

What starts a worker's work.

FieldTypeMeaningDefault
type (required)TriggerTypeschedule, event or onceโ€”
crontextFor a schedule: a cron expression, 0 8 * * *empty
eventtextFor an event: its name, email_receivedempty
attextFor once: when, as an ISO dateempty
descriptiontextWhat it is, in words: Every morning at 8empty
prompttextWhat the worker is told when it firesempty

AppUploadKindโ€‹

A kind of file a person may send, and how large.

FieldTypeMeaningDefault
type (required)textA media type (application/pdf), a family of them (image/*, audio/*) or an extension (.csv), lowercaseโ€”
max_mbnumberThe largest file of this kind, in megabytes; 25 at most10

AppUploadsโ€‹

What a person may send in the composer without being asked: images, files, audio. A file of a kind it does not name, larger than its kind takes, or one too many is refused, in a sentence โ€” by the page before it is sent, and by the runtime when it is sent all the same.

FieldTypeMeaningDefault
kinds (required)list of AppUploadKindThe kinds of file it takes, each with its largest sizeโ€”
max_filesintegerThe most files sent with one message5

AppVerifiedโ€‹

What was verified, and how, each in a sentence a person reads. An example says it on its card and on its page: what was tried live, what runs on recorded data instead, and what is not verified yet. Said by whoever tried it; nothing here is computed.

FieldTypeMeaningDefault
livelist of textWhat was tried live, where and whenโ€”
recordedlist of textWhat runs on recorded data, not on live callsโ€”
unverifiedlist of textWhat is not verified yetโ€”

AppVoiceโ€‹

Its voice: whether it listens, whether it speaks, with which voice, in which language. Off unless said. What is said becomes a message, and what is heard is the answer the conversation shows: the text stays the truth.

FieldTypeMeaningDefault
enabledtrue or falseWhether it has a voice at all; off unless saidfalse
inputVoiceInputoff or push_to_talk (click the microphone or hold it, speak; it stops when let go or once the person stops speaking)"push_to_talk"
outputVoiceOutputWhen its answers are heard: off, on_request (a Read aloud on each answer) or always"on_request"
voicetextThe voice it speaks with, an id of the voice catalogue (kokoro-af-heart); the language's first when unsaidempty
languagetextThe language it listens and speaks in, BCP 47 (en-US, fr-FR); the person's when unsaidempty
whereVoiceWhereWhere its speech runs: auto, device (the person's browser) or server (Datalayer's)"auto"

EmbeddedDeploymentโ€‹

The application inside another product's page.

FieldTypeMeaningDefault
modeEmbedModeinline, bubble, panel or assistant"inline"
originslist of textThe origins allowed to embed itโ€”
hostHostBridgeWhat the host page passes it and the functions of the host it may callempty

HostBridgeโ€‹

What the host page and the application say to each other. The values of the host it reads (context: user, page, or a name of the host's own), through the tool host_context; the functions of the host it may call, each through host_<name>. Every one of these tools is decided by a rule that names it, as any tool is: one no rule names is left to the person. Who its user is (user): what the page says (claimed), or only what the host's server signed (signed) โ€” a short token, HS256 with the deployment's secret, naming sub, name and exp at most an hour away. An application that acts in each user's name, or shows data that is theirs, says signed.

FieldTypeMeaningDefault
contextlist of textThe host's values it reads: user, page, or names of the host's ownโ€”
functionslist of HostFunctionThe host's functions it may callโ€”
userHostUserWho its user is: claimed, what the page says; signed, only a token the host's server signed with the deployment's secret, the unsigned one refused"claimed"

HostFunctionโ€‹

A function of the host page the application's agent may call.

FieldTypeMeaningDefault
name (required)textIts name, lower-case words joined by _: open_ticketโ€”
description (required)textWhat it does, for the agent: when to call itโ€”
parametersmappingIts arguments, as a JSON Schema objectโ€”

HostedDeploymentโ€‹

The application at an address of its own.

FieldTypeMeaningDefault
visibilityVisibilityWho can open it"private"
slugtextThe readable part of its addressempty
avatar_alonetrue or falseAt its address, only its avatar: the conversation opens in its balloon, as when it is shipped as assistantfalse

Model3DAvatarโ€‹

An avatar that is a 3D model (glTF), drawn in the page with three.js.

FieldTypeMeaningDefault
kind (required)model3dmodel3dโ€”
urltextThe https address of its model, a .glb or .gltf; when unsaid, Datalayer's default robot (RobotExpressive, CC0). Its animation named Idle plays while it is quiet; while it speaks, its mouth and head move with its voiceempty

UiChoiceโ€‹

A UI plugin an agent or an application names, and the renderer it is exposed through, when it is.

FieldTypeMeaningDefault
plugin (required)textA UI plugin of agentspecs/ui, by idโ€”
renderertextThe UI renderer of agentspecs/ui-renderers it is exposed through, by idempty

Choicesโ€‹

Accentโ€‹

green, rose, sky, lime, sun, violet

Accessโ€‹

read, write

ActionClassโ€‹

read, write, send, buy, delete, publish

ActsAsโ€‹

owner, user

AppKindโ€‹

chat, widget, decision, worker

BalloonDisplayโ€‹

history, current

Behaviourโ€‹

do_it, if_asked, ask_first, leave_to_me

CheckStageโ€‹

answer, tool_call

CommerceProtocolโ€‹

ucp, acp

CriterionKindโ€‹

metric, noul, choice, score

EmbedModeโ€‹

inline, bubble, panel, assistant

HostUserโ€‹

claimed, signed

Layoutโ€‹

chat, page, split

PairRoleโ€‹

business, personal_agent

PapAgentsโ€‹

any, registered

PapInterfaceโ€‹

agent, openapi, mcp, web

PapReferenceTypeโ€‹

openapi, mcp, web

PapScopeChangesโ€‹

none, reversible, irreversible

PapSignInโ€‹

direct, device, mediated

RecordItemโ€‹

conversations, actions, decisions, approvals, checks, sources, outputs, feedback, audio, diffs, terminals

ThemeModeโ€‹

light, dark, auto

ThemeVariantโ€‹

datalayer, spatial, lovely, matrix, earth, sand, ivory, sun, loop, vscode

TriggerTypeโ€‹

schedule, event, once

Visibilityโ€‹

private, invited, organization, link, public

VoiceInputโ€‹

off, push_to_talk, hands_free

VoiceOutputโ€‹

off, on_request, always

VoiceWhereโ€‹

auto, device, server