On this page

Alternatives between products

A product that needs what another product offers — a model, a picture, a web search, a browser, a secret, a mailbox, a transcript, who a person is, a text or a call — does not dial that product. It asks Stado which alternative answers, and keeps doing every part of its work that does not need it when none does. stado capabilities resolve is that one call; for a model request, a picture or a search, stado capabilities call goes further and hands the request itself to the alternative that answers, so the product never learns which one it was.

Families

The capability catalog declares what products call each other for, the alternatives that answer it in the order they are tried by default, and how a product reaches them. stado capabilities list --json prints every family under alternatives, each with called and, for a family whose alternative is a program, its operations; that listing is the one list, and the table below names the kinds of reach.

Family Alternatives in declared order
inference brama (the service directory route brama), then omp-auth-gateway, then harness-sign-in, then attestation: a statement recorded for the exact request with stado capabilities attestation record, kept under ~/.stado/attestations/inference/<consumer>/ (STADO_ATTESTATIONS moves the root). An agent session's harness (a consumer a session kind's harness.inference.consumer names, such as omp-session for the sessions stado workload start places) is served by brama, by omp-auth-gateway (the harness account gateway the service directory places, proven as a directory route) or by harness-sign-in: the harness's own login on the host that runs the session (omp login anthropic); the last two serve no other consumer. Nothing on the resolving machine answers for harness-sign-in, so its route reads the sign-in <consumer>'s harness holds on each host; each host is asked with stado workload harness signed-in <kind> --alternative <provider> before a session is placed there and again before it starts. stado capabilities call hands neither harness alternative a request. attestation serves every consumer but a harness, since a harness cannot read a statement; an order that leaves a consumer no alternative is refused as consumer-unserved. A session start resolves only among the alternatives its harness declares a route to (model access)
secrets skarbiec (the service directory route skarbiec), then owner-file: the owner-only file store credentials.store names as file://PATH
browser-automation weles (the weles program)
mail skrzynka (the skrzynka program)
transcripts transcript-lake (the transcript-lake program)
messaging skrzynka (the skrzynka program; a product sends what it must tell a person through skrzynka message send instead of a dialog of its own)
image obraz (the obraz program, which runs the request's edit plan), then attestation
journeys probierz (the probierz program): where a release is judged by its product's own journeys, in an account it was installed into, before any delivery reaches a live account (staging)
search search-endpoint (the address capabilities.search.endpoint.url declares, https:// only, with the token of the item playing capabilities.search.endpoint.key_role when one is declared; proven by any HTTP answer from it), then attestation
identity supabase (the identity project the address capabilities.identity.url declares, https:// only, with its capabilities.identity.key_role; proven by any HTTP answer from it): where a product checks a person's session and the organization they act for
telephony wisent-integrations (the action boundary the address capabilities.telephony.url declares, https:// only, with its capabilities.telephony.key_role; proven by any HTTP answer from it): where a product sends a text or places a call without holding the provider account
onboarding-events wisent-integrations (the control plane the address capabilities.onboarding-events.url declares, https:// only, with its capabilities.onboarding-events.key_role; proven by any HTTP answer from it): where a product posts its first-use journey events

A family whose alternative is an address the operator declares refuses to resolve while that address is unset, naming the key and the command that sets it (stado config set capabilities.identity.url https://…), and refuses an address that is not https://; the none-answers refusal below carries each.

A family's order has the environment override Stado's configuration register declares for it: STADO_<FAMILY>_ORDER (STADO_INFERENCE_ORDER, STADO_SECRETS_ORDER, STADO_BROWSER_AUTOMATION_ORDER, STADO_MAIL_ORDER, STADO_TRANSCRIPTS_ORDER, STADO_MESSAGING_ORDER, STADO_IMAGE_ORDER, STADO_JOURNEYS_ORDER, STADO_SEARCH_ORDER, STADO_IDENTITY_ORDER, STADO_TELEPHONY_ORDER, STADO_ONBOARDING_EVENTS_ORDER); the search endpoint's address and key role are STADO_SEARCH_ENDPOINT_URL and STADO_SEARCH_ENDPOINT_KEY_ROLE, and each declared family's are STADO_IDENTITY_URL and STADO_IDENTITY_KEY_ROLE, STADO_TELEPHONY_URL and STADO_TELEPHONY_KEY_ROLE, and STADO_ONBOARDING_EVENTS_URL and STADO_ONBOARDING_EVENTS_KEY_ROLE.

Resolve

stado capabilities resolve inference --consumer oko --json

The answer is the first alternative in the selected order proven to answer: provider, kind (directory, attestation, program, declared or owner-file), route, proven_at, proven_now, fallback (served by an alternative after the first), order, and unreachable, every alternative before it that did not answer, each with its product, route and cause.

When secrets hands out owner-file, credentials.store names that file, and the caller reads the role it needs with stado credentials get --role <role>. The file store keeps no tags, so stado credentials put --role <role> writes the role's item there with the role as its id, and the same --role reads it back; a role no item plays is refused as role-unplayed, naming the role and the put --role that writes it.

An alternative is proven by its own kind: a directory route by stado service directory connect <service> --consumer <consumer>, which knocks on the route and refuses one this host's resolver already holds unanswered; the attestation alternative by its consumer's directory having a place; a program by finding it in Stado's homes or on PATH; an address the operator declares (capabilities.<family>.url, or capabilities.search.endpoint.url) by any HTTP answer to a HEAD request, the address itself being the route handed out; the owner file by finding it. A directory proof waits no longer than the directory refresh interval this host's resolver declares.

An answer from an address is no proof that the service a family looks for answers there: something else may listen at that address. So each kind is proven by a question its owner publishes.

  • A directory route is handed out by stado service directory connect <service> --consumer <consumer> --no-verify, and then asked the question the service catalog declares for the service (service.answering in its catalog part: Brama POST /v1/chat/completions, Skarbiec GET /readyz, Skrzynka GET /healthz, Obraz GET /readyz, Weles GET /healthz). The same declaration is what the host process asks each beacon pass. A success is the service answering, and so is a status the owner publishes as the answer to that question (answers; Brama's 401 to a request with no bearer). A 401 or 403 among those is kept as auth_required: the service answered and asks for the credential the consumer presents itself. A server error is proof-server-error (infra_down), and any other status proof-unanswered (unknown); both rows carry the first line of what the service sent, so Skarbiec's 503 names the item and the key file's own cause. A service whose catalog part declares no question is answering-undeclared (Film today).
  • A declared address handed to a consumer is asked the question its owner publishes, at the address's origin: Wisent Integrations' GET /healthz ("GET /healthz answers readiness"), the Compute Marketplace's GET /healthz (its quick start). An owner whose question no Stado declaration carries is answering-unpublished (Supabase for identity, NeedHer for content-ingest) until it is declared. An address Stado itself sends the family's request (search) is proven by that request, whose answer the call judges. An unset address is address-unset, one that is not https:// address-plain.
  • A program by finding it in Stado's homes or on PATH, and, where its owner publishes a readiness check, by that check ending successfully (preferences doctor --json; its refusal is program-gate-refused, carrying the code the program's own envelope states).
  • The attestation alternative by its consumer's directory having a place; the owner file by finding it.

A proof waits no longer than the directory refresh interval this host's resolver declares, and stands for that same interval: within it, a down first alternative is not asked again, the kept proof names it unreachable and the next alternative serves, so an outage costs one proof per interval, not one per request. A caller that was handed an alternative and was refused by it says so:

stado capabilities resolve inference --consumer oko --failed brama --json

and that alternative is proven again at once. A host whose resolver declares no interval proves every alternative on every resolve.

When none answers

The refusal of the whole family is classed by what its alternatives' rows state, never by their words:

  • none-answers (infra_down, exit 69): at least one row is an outage a later call can outlive (infra_down, rate_limit, timeout); ask again later.
  • none-declared (config, exit 1): every row was refused for a declaration, an absence, a policy or a credential (config, not_found, refused, auth), which asking again will not change; settle what each row names, for example stado service directory consumer add skarbiec <consumer>.
  • none-unclassified (unknown, exit 1): at least one row states no class (a program that refused without its envelope, Skrzynka's not-retryable refusal, a status that is no answer), so whether asking again helps is not known.

Each sentence is resolving <family> for <consumer>: …; observed: <product> at <route>: <cause>; …; with --json the failure envelope's details carry family, consumer, order and unreachable.

A program's refusal keeps the code its own envelope states: the fleet's envelope (error_code, remedy), or Skrzynka's {"error": {"code", "message", "retryable"}}, whose retryable: true is infra_down and retryable: false unknown, since Skrzynka answers it for an absent mailbox and a database failure alike. A program that prints no envelope is unknown, unless it exits with the fleet's retry status (69).

Refusals before anything is proven: family-unknown, consumer-blank and failed-unknown (exit 2); consumer-unserved (exit 2), when the selected order holds no alternative that serves the consumer, naming the ones that would (resolving inference for omp-session: the selected order holds no alternative that serves omp-session); order-config-invalid (exit 1), naming where the order was read from: the family's variable (STADO_<FAMILY>_ORDER, which overrides the configuration) or capabilities.<family>.order (reading inference's selected order from STADO_INFERENCE_ORDER: STADO_INFERENCE_ORDER holds something other than a list of the family's alternatives; observed: …, fix correct or unset STADO_INFERENCE_ORDER …); for a family that lists its consumers, consumer-unlisted (the consumer is not in capabilities.<family>.consumers) and consumers-malformed (exit 1).

What the consumer reads

For a directory route, grants lists the consumer's declared grants from service_directory.services.<service>.consumers.<consumer>.grants: consumer, reads (ROLE#FIELD), token_file and audience; a consumer with none is answered as declaring no grant. The text answer prints the same and an auth required: it answered 401 … line when the route asked for the consumer's credential.

Call: a request answered by whichever alternative answers

stado capabilities call inference --consumer probierz --json < request.json
stado capabilities call inference --consumer stado --operation decisions --json < decision.json

Standard input is one request of the family. For inference, --operation names which gateway request it is (chat, the default, embeddings, decisions, images, speech, speech-timed, music, voices, voice-clone); decisions is Brama's typed decision, {"model": "decision-model", "state", "questions"} answered with answers (https://brama.wisent.com/docs/concepts/decision). Stado resolves the family for the consumer in the selected order and asks the alternative it chose; the answer is printed on standard output (with --json, as {"resolution": …, "answer": …}).

  • brama is sent the request at the route the service directory hands the consumer, with the token of the item playing <consumer>-model-router as its bearer and, when an item plays <consumer>-agent-auth, the request signature made with its agent_auth_secret.
  • attestation answers with the statement recorded for that exact request.

An alternative that cannot answer this request is named with its cause and the next one is asked the same request. A 400 or 422 from Brama is the request itself refused, so no other alternative is asked; its details carry provider, route, status and Brama's whole answer.

A family whose alternative is a program

stado capabilities call browser-automation --consumer slajd --operation open --json <<< '{"url": "https://example.com", "browser": "chromium", "text": true}'
stado capabilities call mail --consumer oko --operation message-list --json <<< '{"organization": "<id>"}'
stado capabilities call preference --consumer jeden --operation read-taste --json <<< '{"arena": "<arena>", "category": "<category>"}'

--operation names one of the commands the program's owner publishes, each listed by stado capabilities list <family> --json with its fields (field, kind, required) and source, the owner's page. Stado runs the program with the operation's words built from the request's fields, and the JSON it prints is the answer; a product names no program and writes no argv of its own.

Family Operation Program's command Published at
browser-automation open weles open <url> --browser … [--headless] [--wait-for-text] [--text] [--screenshot] [--user-data-dir] --json weles.wisent.com/docs/cli/open
session-status, session-stop `weles keeper status stop --session `
subscription-sign-in weles accounts refresh --provider <provider> --subscription <id> --json (request {provider, subscription}, the provider as the subscription's brama:provider: tag names it); Skarbiec signs a due subscription grant in through it weles.wisent.com/docs/cli/accounts-refresh
mail message-list skrzynka message list --organization … [--mailbox --recipient --sender --contains --since --until --limit --offset] skrzynka.wisent.com/docs/cli/message/list
inbound-domains skrzynka mailbox list --inbound --organization … skrzynka.wisent.com/docs/cli/mailbox/list
message-send skrzynka message send --organization … --mailbox … --to … --subject … --body-file … --idempotency-key … skrzynka.wisent.com/docs/cli/message/send
preference read-taste preferences profile --arena … --category … --json preferences.wisent.com/docs/cli

Not declared until their owners publish them: Weles keeper's session start (weles keeper start holds its browser with no published answer that the session is ready) and a session's commands (the frame and the command table are published, the keys of the command object are not); Preferences' put-pair, get-pair and predict.

Refusals before the program runs (exit 2): program-operation-unnamed, program-operation-unknown (each names the family's operations) and request-out-of-shape (names every field, its kind and whether it is required). A program that cannot start is program-unstarted; one that ends unsuccessfully is program-failed, carrying its own code as above; one that prints no JSON is route-not-json. An operation that judges (journeys' stage) answers a negative verdict by ending with status 1 and its JSON answer: that is the answer, since the alternative did judge, and the caller reads the verdict in it; any other unsuccessful end of it is program-failed.

Stado's own judgements

Where Stado decides what a piece of prose means, it asks the inference family as consumer stado. A decision between named options is a typed decision (--operation decisions, model decision-model, one choice question whose criteria are the options). A reading that is a whole object is a chat completion that must call one function under the caller's schema, named with the chat alias the operator declares:

stado config set capabilities.inference.judgement_model <alias>

(STADO_JUDGEMENT_MODEL overrides it). Causes of stado.capabilities.judgement: judgement-model-unset, judgement-uncalled, judgement-not-object, judgement-undecided and judgement-outside; the command that asked reports the judgement as not obtained, never as an answer.

Attestation: answering a request in place of a model

A request no alternative before attestation answered is kept under its SHA-256, and the refusal names the two commands that answer it:

stado capabilities attestation list inference --consumer probierz
stado capabilities attestation show inference --consumer probierz <sha256>
stado capabilities attestation record inference --consumer probierz <sha256> --checked "<what was checked>" < answer
stado capabilities attestation revoke inference --consumer probierz <sha256>

record takes the answer on standard input: for a request whose answer calls a function, the JSON object of that function's arguments (--function NAME when the request offers several and names none); for image and search, the answer in the family's own shape; for any other request, the answer's text. Refusals: checked-blank, answer-blank, answer-out-of-shape, function-invalid, statement-exists, request-not-digest, request-not-kept, request-ambiguous and consumer-invalid. stado capabilities call <family> --consumer <consumer> --await-statement keeps the request and waits until record writes its statement, then prints it as the answer of the same call.

What was served

Every resolve writes its proofs and what it handed out to ~/.stado/capabilities.json (STADO_CAPABILITIES_RECORD moves it): each proof's answered, cause, code and auth_required, and which alternative served which consumer. stado capabilities list [FAMILY] prints each family's order, each alternative's last proof and what served each consumer, a fallback marked as one; --json carries the same under alternatives.

The registry's capabilities section

The canonical registry's capabilities section holds, per family, what the registry declares about who may ask it; today one key, consumers, on a family that lists its consumers (preference):

stado registry set --path capabilities.preference.consumers --value '["jeden"]'

stado registry validate and every registry import, push and set refuse a section that names a family Stado does not declare, a key other than consumers, consumers on a family that admits every consumer, and consumers that is not a list of product names, each naming the key.

Selecting an order

stado capabilities select inference --order attestation,brama

writes capabilities.inference.order, after refusing a name the family does not declare or names twice.

The gate on new code

stado quality check refuses a revision whose added lines dial a service a family offers alternatives for (stado service directory connect brama, forwards/brama, brama.local, and the same for every directory route a family declares) itself; for a called family it also refuses an added line that resolves it. It refuses an added line that starts, itself, a program a family calls through its operations: the program's name given to a process-making call (Command::new("weles"), spawn("weles", …), execFile, Deno.Command) or as the first word of the argument vector one is given (Bun.spawn(["weles", …]), subprocess.run(["weles", …])). An array that only names the program, such as a list of products, starts nothing and is not refused. Each refused line is named with the command that replaces it (stado capabilities call browser-automation --consumer <product>). Only lines the revision adds against the published main are judged; Markdown, tests/, docs/ and .github/ are not read, the program's owner is not judged for its own program, and Stado is not judged by it. A comment line (//, ///, //!, #, /*, a * continuation) and a command quoted in backticks for a reader, as a remedy quotes stado capabilities resolve inference --consumer <product> for the operator to run, describe a call and make none, so neither is judged for dialling or resolving; the same words as code still are.

The same gate refuses, in every product — Stado and web-only releases included — an added line that reaches a provider no Wisent product uses. Resend is one: mail and messages go through Skrzynka. An added dependency on its package (resend-rs in a Cargo.toml, "resend": in a package.json, resend in a requirements*.txt or pyproject.toml) or an added line naming api.resend.com is refused as <path>:<line> adds a dependency on resend, and Resend is never used by any Wisent product; use stado capabilities resolve mail --consumer <product> or stado capabilities resolve messaging --consumer <product> instead: <the line> (or adds the host api.resend.com). Prose, tests, documentation and the forge's automation are not read, as for the rest of this gate, and neither is the one Stado file that declares the forbidden packages and hosts (stado-rs/src/cli/quality/check/reach/forbidden.rs).

How it refuses

Each refusal names the step, the cause, what was observed and the fix, and its cause: line names the functionality that declares it: stado errors show stado.capabilities.alternatives, stado.capabilities.unanswered (one row per alternative), stado.capabilities.attestation, stado.capabilities.record and stado.capabilities.judgement list them all.

Cause Row or refusal Code
none-answers, none-declared, none-unclassified the family infra_down (69), config (1), unknown (1)
consumer-unlisted, consumers-malformed the family config
answering-undeclared, answering-unpublished a row: no question its owner publishes is declared config
proof-server-error a row: the question answered a server error, with its first line infra_down
proof-unanswered a row: a status that is not the service answering, with its first line unknown
route-unreached a row: the request did not reach the address infra_down
program-gate-refused, program-failed a row: the program refused, with its own code the program's
directory-refused a row: the directory refused the consumer, with its own code and remedy the directory's

tests/capabilities/selection.rs, attestation.rs and record.rs provoke ten of them through the real binary; alternatives.rs, await_statement.rs and listing.rs provoke none-answers, not-called, request-not-json, failed-unknown, function-invalid and capability-unknown; declared.rs provokes none-answers for each declared family with its address unset and with an address that is not https://.

Stado Desktop

The Compute providers screen runs Resolve the alternative that answers a product's need in a capability family, Answer a model request, a picture or a search through the alternative that answers it, Choose the order a family's alternatives are tried in, and the attestation operations, each with the CLI's own receipt, beside Read capability families and every provider's support.

Each of these forms reads its Family choices from the selected Stado when it opens, with stado capabilities list --json: every entry of alternatives names its family and called, true for a family products hand to stado capabilities call (inference, image and search), false for one they only resolve. Resolve and Choose the order offer every family; Answer and the attestation operations offer the called ones. A family Stado adds therefore appears in every form without a change to Stado Desktop. When the families cannot be read, the form names why under Family (the command's failure, or a Stado that reports no called, which is updated to one that does) and refuses to run, rather than offering a list of its own.

Source: this website