Studio Authoring and Debugging
Prepare apps for Studio, change run settings, and investigate execution problems.
#Studio Authoring and Debugging
Studio works best when your apps tell it a little about themselves: what prompts to suggest, how to run, and which variant to start with. This guide shows how to author apps so they behave cleanly in Studio, and how to track down problems fast once they are running.
#Authoring Studio-Friendly Apps
For reliable Studio behavior, each app module should expose:
- at least one top-level
AgentorSwarm APP_PROMPTS(recommended)- optional
APP_NAMEandAPP_DESCRIPTION - optional
APP_INVOCATION - optional
APP_CAPABILITIES - optional
configure_variant(variant: str | None)
#Name and Description
Studio names an app after its file (hardware_diagnostics.py shows as "Hardware Diagnostics") and describes it with the first line of the module docstring. Set APP_NAME and APP_DESCRIPTION when you want to say it better. Both must be plain string literals, because the catalog is built by reading the file, not by importing it:
"""Hardware diagnostics demo."""
APP_NAME = "Hardware Diagnostics Assistant"
APP_DESCRIPTION = "Reads a sensor dump and explains which part is failing."The app id and route stay derived from the file name, so renaming the display name never breaks a bookmark. An entry in maivn_studio.json still overrides both, which is the place for a name or description you cannot put in the code.
To see the catalog exactly as Studio will show it, without starting the server or needing an API key:
uv run python -m maivn_studio --list-apps#Prompt Metadata
APP_PROMPTS entries support:
namecontentdescriptionis_defaultstructured_output(tool name)message_type(humanorredacted)variant(pre-select an app variant)
APP_PROMPTS = [
{
"name": "Seed Memory",
"content": "Store this deployment runbook...",
"description": "Seed turn for memory lifecycle",
"is_default": True,
"message_type": "human",
"variant": "focus",
}
]#Invocation Defaults
APP_INVOCATION lets Studio prefill execution options:
APP_INVOCATION = {
"model": "balanced",
"reasoning": "medium",
"memory_config": {
"enabled": True,
"level": "focus",
"summarization_enabled": True,
},
}Studio treats repeated deployments of the same agent as separate invocations. UI code should key cards by invocation, assignment, or action ID rather than agent_name alone.
Supported keys:
modelreasoningforce_final_tooltargeted_toolsmetadatamemory_configsystem_tools_configorchestration_config(accepted for compatibility, but the current SDK does not send it to the runtime)allow_private_in_system_tools
#Conversation and History Capabilities
Interactive Agent and Swarm apps default to conversational behavior with message-history restoration. Authors normally omit APP_CAPABILITIES; Studio then accepts live follow-ups and can offer Continue for an eligible completed session in History.
Declare a single-turn app when a second message would be misleading or unsafe:
APP_CAPABILITIES = {
"interaction_mode": "single_turn",
}Studio then explains that the app allows single-turn runs only and withholds both live follow-up and History Continue. An explicit declaration is authoritative. Invalid interaction modes, restore modes, or value shapes are reported as app configuration errors rather than being replaced with permissive defaults.
A conversational app can also disallow reconstruction from persisted messages while still accepting follow-ups in its current live session:
APP_CAPABILITIES = {
"interaction_mode": "conversation",
"restore_modes": [],
}Use "restore_modes": ["message_history"] to declare that History may reconstruct the conversation. Omitting restore_modes for a conversational app selects that same message-history default. "checkpoint" is also a valid declared restore mode, but it does not by itself authorize Studio's message-history Continue path.
The user-visible paths have different boundaries:
A continuation is not replay or resume. Studio does not rerun prior actions, revive the old Python runtime, or treat an earlier approval as authorization for a new action. Message history supplies conversational context. Separately, an SDK tool dependency may opt one stable producer result into same-thread reuse with result_scope='conversation'; see Dependencies.
#Variant Hook
Use configure_variant when your module must switch runtime wiring:
def configure_variant(variant: str | None) -> None:
if variant == "focus":
...
elif variant == "clarity":
...#Discovery Workflow
When you add a new app, point Studio's discovery at the directory that holds it. Studio rescans on demand from the Scan Repo action in the catalog and merges the result with apps you have already approved.
This keeps config aligned with actual modules and avoids drift in id/module/category.
#Introspection Workflow
Open an app in Studio's catalog and click into the Config tab to confirm how Studio resolved your module:
- resolved agents and swarms
- tool inventory and dependencies
- discovered prompts
- private-data schema
- default invocation (from
APP_INVOCATION)
This is the fastest way to confirm that Studio is reading your module as expected.
#Session Debugging Workflow
- Pick the app, optionally choose a variant, send a controlled test message.
- Watch the Inspect tab for the live SSE stream. (The Inspector also surfaces the Recall tab for memory state, Config for the active invocation config, and Schedule for upcoming scheduled fires.)
- Resolve any
interrupt_requiredprompts inline. - Send follow-ups in the same session to keep
thread_idcontinuity. - Use the per-event detail view for replayable event history.
Studio runs locally for the developer who owns the data, so it keeps full bridge visibility for debugging. If you reuse the same event patterns in a customer-facing app, switch your backend bridge to EventBridge(..., audience="frontend_safe") to apply the safe redaction layer.
If you are debugging duplicate activity in Studio, separate transport replay from logical duplicate delivery:
- replay duplicates usually indicate a reconnect/history issue
- repeated interrupts or adjacent identical status messages usually indicate overlapping producer paths in your own emission code
#Batch Matrix Debugging
Use Studio's Batch Matrix when you need to compare prompts, variants, models, or targeted tools in one grouped turn. Each matrix row becomes one batch item and can override variant, model, reasoning, system_message, and targeted_tools without changing the app module. Uniform batches reuse the top-level invocation settings for every item.
The batch SSE sequence is:
batch_start: pending row metadatabatch_item_complete: one completed row payloadbatch_complete: aggregate status and all item results
#Runtime Patching Without Restart
Studio supports live edits to a loaded app's prompts, descriptions, tags, limits, and per-agent / per-swarm settings while a session is running. Use this for rapid iteration while diagnosing behavior. Saved prompt and description edits persist in maivn_studio.json, and runtime agent/swarm patches apply only to the live loaded instance for the rest of the session.
#Memory-Specific Debugging Tips
For memory apps:
- reuse the same
thread_idacross turns - verify enrichment events:
memory_retrieving,memory_retrieved,memory_indexing - expect some memory/document extraction phases after
final - validate recall using a follow-up query and check hit counts in enrichment payloads
If retrieval appears empty:
- confirm
memory_config.levelis at leastglimpse - confirm thread continuity (
thread_id) - allow short delay for async post-finalize indexing