Docs

Intentions

Let AI agents and your own app ask one running resource of your product, such as a device, to carry out one action your product declared.

What an intention is

An intention asks one resource of a product (a device, a machine, any running host) to carry out one tool the product declared, such as restart. Yayaw decides whether the caller may ask, signs a lease valid for 30 seconds, delivers it to the resource's host, and returns the host's answer: done with a result, or refused with a reason.

It works the same for every product: the product declares its tools as data in its bundle, and Yayaw provides the checks, the delivery and the trail.

Declare the tools

The bundle's intents section lists, for each resource kind, the tools its hosts accept, the action a caller must hold on the resource for each, and the arguments each takes.

"intents": {
  "kinds": [
    {
      "resource": "acme-device",
      "type": "acme-agent-intent+jwt",
      "audience": "urn:yayaw:acme:agent-intent",
      "gateFlag": "acme:agent-intents-enabled",
      "tools": [
        { "name": "restart", "action": "update" },
        { "name": "rotate_key", "action": "manage",
          "arguments": { "keyId": { "type": "string", "maxLength": 64 } } }
      ]
    }
  ]
}
  • type is <product key>-agent-intent+jwt and audience is urn:yayaw:<product key>:agent-intent: a lease for one product is never valid for another.

  • Arguments are a fixed, typed list matched exactly: a host never receives a field its product did not declare.

  • Nothing is issued while gateFlag is off.

Who can ask

CallerHow
An AI agent (Claude, ChatGPT…)The MCP tool yayaw_resource_intent_issue with resource, resourceId, tool, arguments.
Your signed-in appPOST /api/resources/{resource}/{resourceId}/intents with its device session as the bearer.

Both wait for the host's answer and return the same result. Everyone reads their own trail with yayaw_resource_intents_list: the intentions they asked and those asked of a resource they host.

From your app

POST /api/resources/acme-device/device-1/intents
Authorization: Bearer <device session>
Content-Type: application/json

{ "tool": "restart", "arguments": {} }
{ "success": true,
  "data": { "outcome": "done", "jti": "…", "resourceId": "device-1",
            "tool": "restart", "result": { "restarted": true } } }

A refusal by the host is a 200 with "outcome": "refused", a code and a message. The request waits up to the lease's 30 seconds: give your client a timeout above 40 seconds. The host's indicator shows "Signed-in app" for these intentions.

What Yayaw checks

  1. The credential can write.

  2. The resource kind declared intentions and its gateFlag is on.

  3. The tool is declared, and the caller holds its action on this resource through their groups.

  4. The arguments match the declaration.

  5. The resource's host registered its key, and was seen in the last 15 seconds with that key.

CodeStatusMeaning
write_scope_required403The credential cannot write.
forbidden_resource403Undeclared tool, unknown resource or missing right: one answer for all three.
intents_unavailable404The kind declared no intentions, or its flag is off.
invalid_request400The body or the arguments do not match.
resource_identity_unknown409The resource has no registered host key.
resource_unavailable409The host is not running with agent control on.
intent_timeout504No answer in time: the outcome is unknown, read the resource again before retrying.

The host's side

The host signs in with its own device session and:

  1. Beats its presence every few seconds with PUT /api/resources/{resource}/{resourceId}/presence and { "hostFingerprint": "<its key>" }, and removes it with DELETE when it stops accepting intentions.

  2. Reads its leases from /api/dynamic-data/runtime-events with the topic resource-intent:{resource}:{resourceId}, by polling or as a stream. Only the host's account can read them.

  3. Verifies each lease: a JWT signed by the instance (keys at /api/auth/jwks), with your product's type and audience, not expired, naming its own key, a declared tool and declared arguments.

  4. Answers once with POST /api/resources/intents/{jti}/ack and { "outcome": "done", "result": {…} } or { "outcome": "refused", "code": "…", "message": "…" }. The first answer wins.