Skip to content
Get Started

Build an Agent-Drivable Application

A Zebric application becomes agent-drivable when it publishes a small set of semantic operations. Domain commands expose guarded state transitions automatically; skills curate reads, custom routes, and workflow-backed operations. A compatible client discovers these operations from the running application, converts them into tools, and authenticates each request.

This keeps responsibilities clear:

  • The Blueprint defines commands, skills, input types, scopes, policies, and workflows.
  • The runtime enforces authentication, authorization, preconditions, transactions, idempotency, and audit attribution.
  • The agent chooses among the published operations and supplies typed input.
  • External executors such as a browser or test runner perform work outside Zebric, then return bounded evidence through a semantic action.

Prefer commands and skills over broad CRUD

Section titled “Prefer commands and skills over broad CRUD”

Generic entity endpoints are useful for application code, but they are usually too broad for an agent. Define a domain command when an entity transition must have one implementation across generated UI, HTTP, agents, and workflows. Publish a skill for a bounded read, custom projection, or workflow operation that does not map to one record command.

For example, an issue board should expose ClaimIssueForQA rather than allowing an agent to freely update every Issue field. The command can atomically verify that the issue is ready, record who claimed it, and reject stale attempts. A companion skill can expose a filtered list_issues read operation.

[command.ClaimIssueForQA]
entity = "Issue"
description = "Claim a ready issue for one QA run."
policy = "actor.roles contains 'qa'"
availableWhen = "record.qaState == 'ready_to_test'"
mutations = { qaState = "testing", claimedBy = "actor.id" }
scopes = ["qa.claim"]
[skill.issue_board]
description = "Inspect and operate the issue-board QA lifecycle."
[[skill.issue_board.actions]]
name = "list_issues"
description = "List issues, optionally filtered by QA state."
method = "GET"
path = "/api/agent/issues"
entity = "Issue"
action = "list"
scopes = ["qa.list"]
[skill.issue_board.actions.query.qaState]
type = "Enum"
values = ["ready_to_test", "testing", "needs_work", "qa_completed"]
required = false
[[skill.issue_board.actions]]
name = "claim_issue_for_qa"
description = "Atomically claim a Ready to Test issue for one QA run."
method = "POST"
path = "/api/agent/issues/{id}/claim"
entity = "Issue"
workflow = "ClaimIssueForQA"
scopes = ["qa.claim"]
body = {}

The generated operation IDs are <skill>_<action>, such as issue_board_claim_issue_for_qa. Names and descriptions are part of the agent interface: keep them specific, unambiguous, and explicit about preconditions and effects.

An agent starts with the application base URL and requests:

  1. GET /.well-known/zebric-agent.json for capabilities and the OpenAPI location.
  2. GET /api/openapi.json for the exact operation and input schemas.
  3. Protected skill or command routes with a bearer credential.

The discovery document and OpenAPI document carry the same versioned SHA-256 contract fingerprint. Clients should reject a mismatch. A capability set to false means the client must not assume that behavior exists; for example, eventStream: false requires polling instead of subscribing to events.

See the REST API reference for the wire contract, Domain Commands for state transitions, and Skills reference for custom agent operations.

Zebric Agent exposes GET operations automatically. Mutating tools are created only when the application configuration supplies an approval callback, and every mutation is approval-gated. This means an application author should design the contract so that approval is meaningful.

Use this review checklist:

  • Give every action one bounded purpose and a useful description.
  • Prefer typed filters and stable workflow keys over free-form search text.
  • Return only the fields needed for the task; model context is not a data export channel.
  • Use a domain command for a single-record state transition; use a workflow when the operation coordinates multiple commands or side effects.
  • Make mutations transactional, idempotent, observable, and conflict-aware.
  • Require the narrowest scopes that can perform the action.
  • Keep secrets out of descriptions, request bodies, results, and workflow evidence.
  • Expose revision or environment identifiers when stale external work would be unsafe.

Continue with workflow actions, security, and the Zebric Agent overview.