Add MCP tool profiles for workspace chat flows

Expose stable MCP/server tool profiles so chat hosts can start narrow and widen only when needed. This adds vm-run, workspace-core, and workspace-full across the CLI serve path, Pyro.create_server(), and the package-level create_server() factory while keeping workspace-full as the default.

Register profile-specific tool sets from one shared contract mapping, and narrow the workspace-core schemas so secrets, network policy, shells, services, snapshots, and disk tools do not leak into the default persistent chat profile. The full surface remains available unchanged under workspace-full.

Refresh the public docs and examples around the profile progression, add a canonical OpenAI Responses workspace-core example, mark the 3.4.0 roadmap milestone done, and verify with uv lock, UV_CACHE_DIR=.uv-cache make check, UV_CACHE_DIR=.uv-cache make dist-check, and a real guest-backed workspace-core smoke for create, file write, exec, diff, export, reset, and delete.
This commit is contained in:
Thales Maciel 2026-03-12 23:52:13 -03:00
parent 446f7fce04
commit eecfd7a7d7
23 changed files with 984 additions and 511 deletions

View file

@ -22,7 +22,7 @@ Networking: tun=yes ip_forward=yes
```bash
$ uvx --from pyro-mcp pyro env list
Catalog version: 3.3.0
Catalog version: 3.4.0
debian:12 [installed|not installed] Debian 12 environment with Git preinstalled for common agent workflows.
debian:12-base [installed|not installed] Minimal Debian 12 environment for shell and core Unix tooling.
debian:12-build [installed|not installed] Debian 12 environment with Git and common build tools preinstalled.
@ -116,7 +116,7 @@ $ uvx --from pyro-mcp pyro workspace shell open WORKSPACE_ID --secret-env API_TO
$ uvx --from pyro-mcp pyro workspace service start WORKSPACE_ID app --secret-env API_TOKEN --ready-file .ready -- sh -lc 'touch .ready && while true; do sleep 60; done'
$ uvx --from pyro-mcp pyro workspace create debian:12 --network-policy egress+published-ports
$ uvx --from pyro-mcp pyro workspace service start WORKSPACE_ID app --ready-http http://127.0.0.1:8080/ --publish 18080:8080 -- ./start-app
$ uvx --from pyro-mcp pyro mcp serve
$ uvx --from pyro-mcp pyro mcp serve --profile workspace-core
```
`pyro demo` proves the one-shot create/start/exec/delete VM lifecycle works end to end.
@ -252,7 +252,7 @@ State: started
Use `--seed-path` when the workspace should start from a host directory or a local
`.tar` / `.tar.gz` / `.tgz` archive instead of an empty `/workspace`. Use
`pyro workspace sync push` when you need to import later host-side changes into a started
workspace. Sync is non-atomic in `3.3.0`; if it fails partway through, prefer `pyro workspace reset`
workspace. Sync is non-atomic in `3.4.0`; if it fails partway through, prefer `pyro workspace reset`
to recover from `baseline` or one named snapshot. Use `pyro workspace diff` to compare the current
`/workspace` tree to its immutable create-time baseline, `pyro workspace snapshot *` to create
named checkpoints, and `pyro workspace export` to copy one changed file or directory back to the

View file

@ -85,7 +85,7 @@ uvx --from pyro-mcp pyro env list
Expected output:
```bash
Catalog version: 3.3.0
Catalog version: 3.4.0
debian:12 [installed|not installed] Debian 12 environment with Git preinstalled for common agent workflows.
debian:12-base [installed|not installed] Minimal Debian 12 environment for shell and core Unix tooling.
debian:12-build [installed|not installed] Debian 12 environment with Git and common build tools preinstalled.
@ -224,7 +224,7 @@ After the CLI path works, you can move on to:
- interactive shells: `pyro workspace shell open WORKSPACE_ID`
- long-running services: `pyro workspace service start WORKSPACE_ID app --ready-file .ready -- sh -lc 'touch .ready && while true; do sleep 60; done'`
- localhost-published ports: `pyro workspace create debian:12 --network-policy egress+published-ports` and `pyro workspace service start WORKSPACE_ID app --ready-http http://127.0.0.1:8080/ --publish 18080:8080 -- ./start-app`
- MCP: `pyro mcp serve`
- MCP: `pyro mcp serve --profile workspace-core`
- Python SDK: `from pyro_mcp import Pyro`
- Demos: `pyro demo` or `pyro demo --network`
@ -274,7 +274,7 @@ Workspace commands default to the persistent `/workspace` directory inside the g
the identifier programmatically, use `--json` and read the `workspace_id` field. Use `--seed-path`
when the workspace should start from a host directory or a local `.tar` / `.tar.gz` / `.tgz`
archive. Use `pyro workspace sync push` for later host-side changes to a started workspace. Sync
is non-atomic in `3.3.0`; if it fails partway through, prefer `pyro workspace reset` to recover
is non-atomic in `3.4.0`; if it fails partway through, prefer `pyro workspace reset` to recover
from `baseline` or one named snapshot. Use `pyro workspace diff` to compare the current workspace
tree to its immutable create-time baseline, `pyro workspace snapshot *` to capture named
checkpoints, and `pyro workspace export` to copy one changed file or directory back to the host. Use

View file

@ -7,8 +7,10 @@ CLI path in [install.md](install.md) or [first-run.md](first-run.md).
## Recommended Default
Use `vm_run` first for one-shot commands, then move to the stable workspace surface when the
agent needs to inhabit one sandbox across multiple calls.
Use `vm_run` first for one-shot commands, then move to `workspace-core` when the
agent needs to inhabit one sandbox across multiple calls. Only promote the chat
surface to `workspace-full` when it truly needs shells, services, snapshots,
secrets, network policy, or disk tools.
That keeps the model-facing contract small:
@ -17,8 +19,11 @@ That keeps the model-facing contract small:
- one ephemeral VM
- automatic cleanup
Move to `workspace_*` when the agent needs repeated commands, shells, services, snapshots, reset,
diff, or export in one stable workspace across multiple calls.
Profile progression:
- `vm-run`: one-shot only
- `workspace-core`: persistent workspace create/list/update/status/sync/exec/logs/file ops/diff/export/reset/delete
- `workspace-full`: the full stable workspace surface, including shells, services, snapshots, secrets, network policy, and disk tools
## OpenAI Responses API
@ -30,20 +35,14 @@ Best when:
Recommended surface:
- `vm_run`
- `workspace_create(name=..., labels=...)` + `workspace_list` + `workspace_update` when the agent needs to rediscover or retag long-lived workspaces between turns
- `workspace_create(seed_path=...)` + `workspace_sync_push` + `workspace_exec` when the agent needs persistent workspace state
- `workspace_file_list` / `workspace_file_read` / `workspace_file_write` / `workspace_patch_apply` when the agent needs model-native file inspection and text edits inside one live workspace
- `workspace_create(..., secrets=...)` + `workspace_exec(..., secret_env=...)` when the workspace needs private tokens or authenticated setup
- `workspace_create(..., network_policy="egress+published-ports")` + `start_service(..., published_ports=[...])` when the host must probe one workspace service
- `workspace_diff` + `workspace_export` when the agent needs explicit baseline comparison or host-out file transfer
- `stop_workspace(...)` + `list_workspace_disk(...)` / `read_workspace_disk(...)` / `export_workspace_disk(...)` when one stopped guest-backed workspace needs offline inspection or a raw ext4 copy
- `start_service` / `list_services` / `status_service` / `logs_service` / `stop_service` when the agent needs long-running processes inside that workspace
- `open_shell(..., secret_env=...)` / `read_shell` / `write_shell` when the agent needs an interactive PTY inside that workspace
- `vm_run` for one-shot loops
- the `workspace-core` tool set for the normal persistent chat loop
- the `workspace-full` tool set only when the host explicitly needs advanced workspace capabilities
Canonical example:
- [examples/openai_responses_vm_run.py](../examples/openai_responses_vm_run.py)
- [examples/openai_responses_workspace_core.py](../examples/openai_responses_workspace_core.py)
## MCP Clients
@ -55,7 +54,13 @@ Best when:
Recommended entrypoint:
- `pyro mcp serve`
- `pyro mcp serve --profile workspace-core`
Profile progression:
- `pyro mcp serve --profile vm-run` for the smallest one-shot surface
- `pyro mcp serve --profile workspace-core` for the normal persistent chat loop
- `pyro mcp serve --profile workspace-full` only when the model truly needs advanced workspace tools
Starter config:

View file

@ -82,6 +82,7 @@ Behavioral guarantees:
- `pyro workspace create --seed-path PATH` seeds `/workspace` from a host directory or a local `.tar` / `.tar.gz` / `.tgz` archive before the workspace is returned.
- `pyro workspace create --name NAME --label KEY=VALUE` attaches human-oriented discovery metadata without changing the stable `workspace_id`.
- `pyro workspace create --network-policy {off,egress,egress+published-ports}` controls workspace guest networking and whether services may publish localhost ports.
- `pyro mcp serve --profile {vm-run,workspace-core,workspace-full}` narrows the model-facing MCP surface without changing runtime behavior.
- `pyro workspace create --secret NAME=VALUE` and `--secret-file NAME=PATH` persist guest-only UTF-8 secrets outside `/workspace`.
- `pyro workspace list` returns persisted workspaces sorted by most recent `last_activity_at`.
- `pyro workspace sync push WORKSPACE_ID SOURCE_PATH [--dest WORKSPACE_PATH]` imports later host-side directory or archive content into a started workspace.
@ -125,8 +126,8 @@ Primary facade:
Supported public entrypoints:
- `create_server()`
- `Pyro.create_server()`
- `create_server(profile="workspace-full")`
- `Pyro.create_server(profile="workspace-full")`
- `Pyro.list_environments()`
- `Pyro.pull_environment(environment)`
- `Pyro.inspect_environment(environment)`
@ -176,7 +177,7 @@ Supported public entrypoints:
Stable public method names:
- `create_server()`
- `create_server(profile="workspace-full")`
- `list_environments()`
- `pull_environment(environment)`
- `inspect_environment(environment)`
@ -265,6 +266,18 @@ Behavioral defaults:
## MCP Contract
Stable MCP profiles:
- `vm-run`: exposes only `vm_run`
- `workspace-core`: exposes `vm_run`, `workspace_create`, `workspace_list`, `workspace_update`, `workspace_status`, `workspace_sync_push`, `workspace_exec`, `workspace_logs`, `workspace_file_list`, `workspace_file_read`, `workspace_file_write`, `workspace_patch_apply`, `workspace_diff`, `workspace_export`, `workspace_reset`, and `workspace_delete`
- `workspace-full`: exposes the complete stable MCP surface below
Behavioral defaults:
- `pyro mcp serve` and `create_server()` default to `workspace-full`.
- `workspace-core` narrows `workspace_create` by omitting `network_policy` and `secrets`.
- `workspace-core` narrows `workspace_exec` by omitting `secret_env`.
Primary tool:
- `vm_run`

View file

@ -6,7 +6,7 @@ goal:
make the core agent-workspace use cases feel trivial from a chat-driven LLM
interface.
Current baseline is `3.3.0`:
Current baseline is `3.4.0`:
- the stable workspace contract exists across CLI, SDK, and MCP
- one-shot `pyro run` still exists as the narrow entrypoint
@ -47,7 +47,7 @@ More concretely, the model should not need to:
1. [`3.2.0` Model-Native Workspace File Ops](llm-chat-ergonomics/3.2.0-model-native-workspace-file-ops.md) - Done
2. [`3.3.0` Workspace Naming And Discovery](llm-chat-ergonomics/3.3.0-workspace-naming-and-discovery.md) - Done
3. [`3.4.0` Tool Profiles And Canonical Chat Flows](llm-chat-ergonomics/3.4.0-tool-profiles-and-canonical-chat-flows.md)
3. [`3.4.0` Tool Profiles And Canonical Chat Flows](llm-chat-ergonomics/3.4.0-tool-profiles-and-canonical-chat-flows.md) - Done
4. [`3.5.0` Chat-Friendly Shell Output](llm-chat-ergonomics/3.5.0-chat-friendly-shell-output.md)
5. [`3.6.0` Use-Case Recipes And Smoke Packs](llm-chat-ergonomics/3.6.0-use-case-recipes-and-smoke-packs.md)
@ -58,6 +58,9 @@ Completed so far:
- `3.3.0` added workspace names, key/value labels, `workspace list`, `workspace update`, and
`last_activity_at` tracking so humans and chat-driven agents can rediscover and resume the right
workspace without external notes.
- `3.4.0` added stable MCP/server tool profiles with `vm-run`, `workspace-core`, and
`workspace-full`, plus canonical profile-based OpenAI and MCP examples so chat hosts can start
narrow and widen only when needed.
## Expected Outcome

View file

@ -1,6 +1,6 @@
# `3.4.0` Tool Profiles And Canonical Chat Flows
Status: Planned
Status: Done
## Goal