Turn the stable workspace surface into five documented, runnable stories with a shared guest-backed smoke runner, new docs/use-cases recipes, and Make targets for cold-start validation, repro/fix loops, parallel workspaces, untrusted inspection, and review/eval workflows. Bump the package and catalog surface to 3.6.0, update the main docs to point users from the stable workspace walkthrough into the recipe index and smoke packs, and mark the 3.6.0 roadmap milestone done. Fix a regression uncovered by the real parallel-workspaces smoke: workspace_file_read must not bump last_activity_at. Verified with uv lock, UV_CACHE_DIR=.uv-cache make check, UV_CACHE_DIR=.uv-cache make dist-check, and USE_CASE_ENVIRONMENT=debian:12 UV_CACHE_DIR=.uv-cache make smoke-use-cases.
160 lines
7 KiB
Markdown
160 lines
7 KiB
Markdown
# Integration Targets
|
|
|
|
These are the main ways to integrate `pyro-mcp` into an LLM application.
|
|
|
|
Use this page after you have already validated the host and guest execution through the
|
|
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 `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:
|
|
|
|
- one tool
|
|
- one command
|
|
- one ephemeral VM
|
|
- automatic cleanup
|
|
|
|
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
|
|
|
|
Best when:
|
|
|
|
- your agent already uses OpenAI models directly
|
|
- you want a normal tool-calling loop instead of MCP transport
|
|
- you want the smallest amount of integration code
|
|
|
|
Recommended surface:
|
|
|
|
- `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)
|
|
- [docs/use-cases/repro-fix-loop.md](use-cases/repro-fix-loop.md)
|
|
|
|
## MCP Clients
|
|
|
|
Best when:
|
|
|
|
- your host application already supports MCP
|
|
- you want `pyro` to run as an external stdio server
|
|
- you want tool schemas to be discovered directly from the server
|
|
|
|
Recommended entrypoint:
|
|
|
|
- `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:
|
|
|
|
- [examples/mcp_client_config.md](../examples/mcp_client_config.md)
|
|
- [examples/claude_desktop_mcp_config.json](../examples/claude_desktop_mcp_config.json)
|
|
- [examples/cursor_mcp_config.json](../examples/cursor_mcp_config.json)
|
|
- [docs/use-cases/README.md](use-cases/README.md)
|
|
|
|
## Direct Python SDK
|
|
|
|
Best when:
|
|
|
|
- your application owns orchestration itself
|
|
- you do not need MCP transport
|
|
- you want direct access to `Pyro`
|
|
|
|
Recommended default:
|
|
|
|
- `Pyro.run_in_vm(...)`
|
|
- `Pyro.create_workspace(name=..., labels=...)` + `Pyro.list_workspaces()` + `Pyro.update_workspace(...)` when repeated workspaces need human-friendly discovery metadata
|
|
- `Pyro.create_workspace(seed_path=...)` + `Pyro.push_workspace_sync(...)` + `Pyro.exec_workspace(...)` when repeated workspace commands are required
|
|
- `Pyro.list_workspace_files(...)` / `Pyro.read_workspace_file(...)` / `Pyro.write_workspace_file(...)` / `Pyro.apply_workspace_patch(...)` when the agent needs model-native file inspection and text edits inside one live workspace
|
|
- `Pyro.create_workspace(..., secrets=...)` + `Pyro.exec_workspace(..., secret_env=...)` when the workspace needs private tokens or authenticated setup
|
|
- `Pyro.create_workspace(..., network_policy="egress+published-ports")` + `Pyro.start_service(..., published_ports=[...])` when the host must probe one workspace service
|
|
- `Pyro.diff_workspace(...)` + `Pyro.export_workspace(...)` when the agent needs baseline comparison or host-out file transfer
|
|
- `Pyro.start_service(..., secret_env=...)` + `Pyro.list_services(...)` + `Pyro.logs_service(...)` when the agent needs long-running background processes in one workspace
|
|
- `Pyro.open_shell(..., secret_env=...)` + `Pyro.write_shell(...)` + `Pyro.read_shell(..., plain=True, wait_for_idle_ms=300)` when the agent needs an interactive PTY inside the workspace
|
|
|
|
Lifecycle note:
|
|
|
|
- `Pyro.exec_vm(...)` runs one command and auto-cleans the VM afterward
|
|
- use `create_vm(...)` + `start_vm(...)` only when you need pre-exec inspection or status before
|
|
that final exec
|
|
- use `create_workspace(seed_path=...)` when the agent needs repeated commands in one persistent
|
|
`/workspace` that starts from host content
|
|
- use `create_workspace(name=..., labels=...)`, `list_workspaces()`, and `update_workspace(...)`
|
|
when the agent or operator needs to rediscover the right workspace later without external notes
|
|
- use `push_workspace_sync(...)` when later host-side changes need to be imported into that
|
|
running workspace without recreating it
|
|
- use `list_workspace_files(...)`, `read_workspace_file(...)`, `write_workspace_file(...)`, and
|
|
`apply_workspace_patch(...)` when the agent should inspect or edit workspace files without shell
|
|
quoting tricks
|
|
- use `create_workspace(..., secrets=...)` plus `secret_env` on exec, shell, or service start when
|
|
the agent needs private tokens or authenticated startup inside that workspace
|
|
- use `create_workspace(..., network_policy="egress+published-ports")` plus
|
|
`start_service(..., published_ports=[...])` when the host must probe one service from that
|
|
workspace
|
|
- use `diff_workspace(...)` when the agent needs a structured comparison against the immutable
|
|
create-time baseline
|
|
- use `export_workspace(...)` when the agent needs one file or directory copied back to the host
|
|
- use `stop_workspace(...)` plus `list_workspace_disk(...)`, `read_workspace_disk(...)`, or
|
|
`export_workspace_disk(...)` when the agent needs offline inspection or one raw ext4 copy from
|
|
a stopped guest-backed workspace
|
|
- use `start_service(...)` when the agent needs long-running processes and typed readiness inside
|
|
one workspace
|
|
- use `open_shell(...)` when the agent needs interactive shell state instead of one-shot execs
|
|
|
|
Examples:
|
|
|
|
- [examples/python_run.py](../examples/python_run.py)
|
|
- [examples/python_lifecycle.py](../examples/python_lifecycle.py)
|
|
- [examples/python_workspace.py](../examples/python_workspace.py)
|
|
- [examples/python_shell.py](../examples/python_shell.py)
|
|
- [docs/use-cases/README.md](use-cases/README.md)
|
|
|
|
## Agent Framework Wrappers
|
|
|
|
Examples:
|
|
|
|
- LangChain tools
|
|
- PydanticAI tools
|
|
- custom in-house orchestration layers
|
|
|
|
Best when:
|
|
|
|
- you already have an application framework that expects a Python callable tool
|
|
- you want to wrap `vm_run` behind framework-specific abstractions
|
|
|
|
Recommended pattern:
|
|
|
|
- keep the framework wrapper thin
|
|
- map one-shot framework tool input directly onto `vm_run`
|
|
- expose `workspace_*` only when the framework truly needs repeated commands in one workspace
|
|
|
|
Concrete example:
|
|
|
|
- [examples/langchain_vm_run.py](../examples/langchain_vm_run.py)
|
|
|
|
## Selection Rule
|
|
|
|
Choose the narrowest integration that matches the host environment:
|
|
|
|
1. OpenAI Responses API if you want a direct provider tool loop.
|
|
2. MCP if your host already speaks MCP.
|
|
3. Python SDK if you own orchestration and do not need transport.
|
|
4. Framework wrappers only as thin adapters over the same `vm_run` contract.
|