@obversa/engine-mastra makes a Mastra agent one engine: a node the runtime
can review, send back with findings, pause, resume and record. The agent’s
tools, memory and workflows stay Mastra’s.
The engine runs the agent your code builds. It loads none of your own
setup, so it always runs clean and has no clean option. Its row in the
engines table says the same.
Install
@obversa/obversa; install it on its own, beside Mastra.
Requirements
- Node.js 22.13 or later, which
@mastra/coreneeds. @mastra/core1.74 or a later 1.x release.- Whatever your agent needs to run, such as its model provider’s key.
A seat for a team
Build the agent the way you already do. This one has its own instructions, its own model and its own tool, which saves a file:examples/engine-mastra.ts (excerpt)
mastra(agent) makes it a seat, the way claude('claude-sonnet-4-5') makes
a Claude seat. Give the seat a role in a workflow(). Here the Mastra agent
writes, Codex reviews, and a judge decides whether another round runs:
examples/engine-mastra.ts (excerpt)
What crosses the boundary
Each attempt is one call to the agent’s owngenerate. The engine sends
three things:
- The prompt of the request.
- The system text, when the request has some. It goes to Mastra’s
systemoption, or to itsinstructionsoption when the request replaces the system prompt. - An abort signal that fires when the run aborts or the request’s timeout passes.
- The agent’s final text, as the result.
- The usage Mastra reports, or
unknownwhen Mastra reports none. - The seat’s identity: adapter
mastra, with the provider and model the agent is built with.
What stays Mastra’s
The agent’s tools, memory and any Mastra workflow inside it stay Mastra’s. The engine does not turn Mastra tools into Obversa tools, and it passes no working directory to the agent. So a step’s declared Obversa tools and read-only mode do not limit a Mastra agent. It uses the tools it was built with, wherever those tools act. In the example, the agent’s own tool saves the page into the directory the run starts in. How hard the model thinks stays Mastra’s too: set it on the agent. The seat’seffort option and a step’s effort are not supported, and setting
either throws an error that says so.
The review, send-back, pause, resume and record around the agent work as
for any engine. A Mastra seat declares no Obversa tools, so the runtime
does not accept it as a reviewer: a reviewer must declare a tool that reads
the workspace.
Identity
The seat reads the provider and model from the model the agent is built with: aprovider/model string, a language model object, an
OpenAI-compatible config, or a fallback list, where it reads the first
enabled entry. The model family is the model name after its last /, up to
its first hyphen, so claude-sonnet-4-5 is the family claude.
When the agent chooses its model with a function, the seat cannot read it
before the run, and mastra() throws. Name the model yourself:
mastra(agent, { model: 'openai/gpt-5' }).
Errors
- A rate limit: a thrown error with status 429. The provider’s
retry-afterheader, when there is one, is kept. - Everything else goes through the shared classification, so a quota, authentication or billing message is typed as one.
abortedwhen the run aborts, andtimeoutwhen the request’stimeoutMs, plustimeoutGraceMswhen set, passes.
What the run did
Run offline, with the agent’s model replaying its turns fromwriter.json,
a stand-in for the Codex command line tool, and the judge’s answers
replayed from judge.json, the example printed:
Output
saveFile tool, then
replied. The first reader pass found two blocks, so the page went back to
the agent. The second found one nice-to-have, and the judge chose
holds. The record holds both runs of the agent with the usage Mastra
reported for each.
API
mastra: the seat for a team workflow.MastraSeatandMastraSeatOptions: its types. A seat for a team.MastraEngine: the engine the seat holds.MastraAgent: the part of a MastraAgentthe engine reads and calls.
Next steps
- Runtime: the roles a seat fills.
- Know when to stop: the stopping rule this example uses.
- API: the engine contract the plugin implements.