Mastra adapter
@astropods/adapter-mastra runs a Mastra Agent on Astropods. With one call your agent chats with users, streams its progress, handles voice, and is traced, with no extra wiring.
Install
Requires @mastra/core >= 1.14.0 as a peer dependency.
Quick start
serve(agent) runs until the process exits. The same code works locally and when deployed.
API
serve(agent, options?)
Connects a Mastra Agent to the messaging service and starts listening.
ServeOptions
MastraAdapterOptions
The model sees attached images directly. For any other file it gets the file’s path, so give an agent that accepts documents a tool that reads a file from a path. Without one, the model tends to describe a file it never read. For full control over attachments, write a custom adapter.
MastraAdapter
The class behind serve(). Use it directly if you need custom lifecycle control:
Memory
Conversation memory and per-user traces work without setup. Each conversation is its own memory thread, and each user is its own resource.
When a user edits a message in the web chat, the adapter rebuilds the conversation’s thread from the turns before the edit, so the agent forgets the replaced turns. Thread-scoped working memory starts over with it.
Voice
Configure a Mastra voice provider on the agent (see Mastra’s voice docs) to accept voice messages. The agent transcribes what the user said, replies, and speaks the reply when the provider can synthesize speech. Without a voice provider, the user gets a friendly error for a voice message.
Tracing
A deployed agent is traced with no code changes. Every model call and tool call appears as a span, and each response, along with any feedback on it, links back to its trace.
Example: an agent with tools
Tool names and descriptions show in the playground. While a tool runs, the user sees Running customer_lookup, then Finished customer_lookup.
Sandboxes
Give a Mastra Workspace an Astropods sandbox, and its built-in tools run commands and edit files in an isolated VM instead of on the agent’s own machine. Declare a sandbox in astropods.yml first, as Sandbox client describes.
Use the thread id as name, so a resumed conversation gets its own files back and two threads never share them. AstroSandboxOptions accepts every SandboxClient option, plus client to share one client across sandboxes.
The workspace tells the model about the sandbox, including that long work belongs in a background process, so you do not add that to the agent’s instructions.
executeCommandruns its command through a shell. PassonStdoutoronStderrto stream output while the command runs.stop()suspends the sandbox, anddestroy()deletes it and its files.snapshot()also suspends. There are no checkpoints to restore later.
See Sandbox client for lifecycle thresholds, caps, and limitations. Sandboxes are experimental.
Local development
Chat with the agent at http://localhost:3100. See ast project for the other commands.
FAQ
Where does serve() connect?
To the Astropods messaging service at localhost:9090, or GRPC_SERVER_ADDR when set. ast project start and a deployment both set it, so you only pass serverAddress to override it.
Which Mastra stream chunks become status updates?
Other chunk types are ignored. To map more, subclass MastraAdapter and override stream().
What happens to a voice message?
The adapter receives the audio, transcribes it with voice.listen, and shows the transcript in the conversation. It then runs the agent on the transcript and, when voice.speak exists, streams the spoken reply back. The audio format comes from the message’s encoding (see Audio).
How does tracing turn on?
Astropods sets OTEL_EXPORTER_OTLP_ENDPOINT on a deployed agent, and serve() turns on Mastra’s observability when it is set. The adapter attaches each turn’s trace context to its responses, which is how feedback links to a trace (see Trace context).
Which sandbox call does each Mastra method use?
Why does my once-per-VM workspace setup run on every start()?
start() always reports the created outcome, because Astropods does not say whether an attach launched a new VM or resumed a suspended one. Reporting created repeats setup rather than risk skipping it on a new machine. Keep that setup safe to run twice.
Does a workspace tool launch a sandbox just to show its status?
No. Mastra reads the sandbox’s status at the start of every workspace tool, and getInfo() reports a sandbox that does not exist yet without creating one.