Skip to content
Concept

Agent Resource Data Runtime

How Core derives generic Agent read and write tools from App-owned Resource, permission, schema, route, and controller contracts.

Agent Resource Data Runtime

Make the normal Resource contract complete: publish its model and permissions, declare fields, and keep matching read/write controller routes. Start with Create a Resource. An authorized Agent should then discover only supported operations through data.catalog and data.describe; no generic Agent adapter belongs in your App.

Prepare the Resource

Agent Resource Data is the Core runtime that turns ordinary App-owned Resources into governed Agent data operations. It publishes the generic data.catalog, data.describe, data.query, data.detail, data.preview, data.verify, data.mutate, data.mutate_batch, and data.action tool flow. Apps do not register those tools and do not import Agent classes from Core. Instead, Core derives the available surface from declarations the App already owns: its Resource catalog entry, Eloquent model, permissions, Resource descriptor, list schema, API routes, controller, and request validation.

Agent tools

AgentDataResourceRegistry starts with the Core-governed Resource catalog. A Resource participates only when its contribution exposes both a PermissionContribution and an Eloquent model. The registry reads the Resource's own permission definitions; missing either contract excludes the Resource rather than inventing defaults.

The tool flow separates discovery, preflight, and execution:

StageResult
data.catalogLists only Resources visible to the actor and suitable for generic data access
data.describeReturns the Resource's fields, capabilities, filters, sorts, search behavior, reference metadata, and allowed lifecycle actions
data.queryExecutes a bounded query after current tenant and Resource authorization
data.detailReads one record through its authorized App detail API, including its domain DTO
data.previewExecutes a declared read-only domain evaluator using its exact HTTP method and schema
data.verifyPerforms side-effect-free write preflight and returns a verdict for each proposed record
data.mutateExecutes one approved create, update, or delete through the Resource API
data.mutate_batchExecutes an approved plan sequentially and records each outcome
data.actionRuns a declared lifecycle verb such as submit or cancel through the Resource's own action endpoint after confirmation

AgentDataFieldSchema resolves field descriptions in a fixed priority: ResourceDescriptor first, Resource transfer columns second, and database schema last. The response reports that field_source so a caller can distinguish an intentional domain declaration from fallback inference. Filter, sort, and search capability come from the list schema rather than being guessed from a column. Reference fields retain Resource identity and display-label metadata.

The write flow also reuses the Resource API. AgentDataWriteRoutes requires the model and controller basenames to match inside the same App namespace, then pairs each write with that controller's exact GET collection or member URI: POST for create, PUT or PATCH for update, and DELETE for delete. This is the route shape emitted by nexia-apps:make-package-resource; Laravel scoped bindings such as {legalEntity:public_id} are filled from trusted delegation context. Therefore Form Request validation, policies, transactions, domain services, and events remain in force. A missing controller, missing read/write pair, or more than one candidate leaves the action unsupported; the generic runtime never writes an Eloquent model directly.

Nested child Resources use AgentScopedRouteResolver. A nested child Resource is reachable only under its resolved parent route and cannot be addressed as an unscoped top-level record. This protects both route identity and parent authorization.

For an approved batch, Core stores an actor-scoped registration run. One user approval authorizes the submitted plan, then outcomes are recorded sequentially as the run moves through pending, running, and completed, partial, or failed. The batch is ordered and best effort, not one atomic transaction across all records. A later failure does not claim that earlier successful controller requests were rolled back.

Authorization and validation

agent.data.read only opens the generic tool surface; each Resource still requires its current permission. Writes also require agent.data.write, the Resource action permission, and approval for the write-tier tool.

An App must not import App\Agent\* or register Core's generic routes. Publish normal SDK contributions and normal App routes. Core discovers them through the installed App map and preserves the request's tenant boundary and authenticated user through the App route.

Do not treat data.verify as a reservation or authorization token. It is a side-effect-free preflight against current inputs; the approved write is authorized and validated again when executed. Likewise, a catalog result is not a durable grant. Permission and App operational state are evaluated at use time.

Generic data does not bypass Resource-specific invariants. If a domain write cannot be expressed safely through the Resource's public controller route, leave that action unsupported or publish a purpose-built route-backed tool through the SDK Contribution contracts. Do not weaken controller validation so the generic runtime can force an otherwise invalid record through.

Keep field metadata intentional. Database fallback makes a Resource inspectable, but a ResourceDescriptor is the correct owner for user-facing descriptions, enum values, localized label keys, reference semantics, and field intent. Request validation remains the authority for accepted writes. Do not expose secrets, internal bookkeeping columns, or values that the ordinary API would not return.

Resource operations and complete discovery

Declare reusable operations in ResourceDescriptor::$actions, using ResourceActionDescriptor with an exact permission, HTTP method, route path, and inputSchema. The action key does not imply its permission: a reject action can require approve. Declare ResourceActionEffect::Read only for side-effect-free evaluators; mutations use Mutate. Optional description explains state requirements and business meaning. data.describe exposes these contracts without adding a model tool for every Resource action.

Declare ResourceDescriptor::$mutation with ResourceMutationDescriptor(createInputSchema: ..., updateInputSchema: ...) to preserve the complete accepted payload, including nested lines. A field schema alone is not a write contract. The existing controller remains authoritative for validation, authorization, and state changes.

Follow data.catalog.next_cursor until it is null to traverse all authorized Resources. app.navigation.read discovers installed, accessible Apps and their descriptions; include_guides returns guide summaries and guide retrieves one guide's steps. Resources and navigation have different eligibility rules. Neither response claims access to unavailable Apps or unauthorized Resources.

App-specific tools remain available through AgentToolContribution for a distinct business capability that generic Resource operations cannot represent. Do not register duplicate list/show/create/update tools. Multi-step guidance can use Feature Guides; executable business steps can use Process Work Action contributions. A guide explains a workflow and does not grant permission or implement the workflow itself.

Check the result

For your generated Resource, compare data.describe with its declared fields and supported controller routes. A query must enforce the same read permission as the browser API. An approved mutation must reach the same validation and domain action. If an App is unavailable or a permission is revoked, the next operation must refuse access.

Source of truth: docs/developers/content/en/core-runtime/agent-resource-data.md