Mirage
haystack_integrations.tools.mirage.shell_tool
MirageShellTool
Bases: Tool
A Haystack Tool that lets an Agent run bash commands across a Mirage virtual filesystem.
Mirage mounts heterogeneous backends (object storage, databases, SaaS apps, local disk) as one
filesystem; this tool exposes Mirage's single execute surface to an Agent as one well-described
tool with a command parameter. Output is normalized to text and truncated before it reaches the
model.
Security model
Mirage never shells out to the host: every command runs inside Mirage's own virtual-filesystem interpreter, so the blast radius is confined to the mounts you attach. Two controls shape what an Agent can do:
- Per-mount read-only mode (
MirageMount(..., read_only=True)) is the authoritative write boundary. Mirage refuses any write to a read-only mount regardless of the command used, so this -- not the allowlist -- is how you prevent modification or deletion. Mount anything the Agent should not change as read-only. - The command allowlist (
allowed_commands) restricts which commands may run. It is enforced against every command Mirage would execute, including commands nested inside$(...), backticks,<(...)and subshells, sols "$(rm x)"is rejected unlessrmis also allowed. Treat it as a best-effort filter to steer the Agent, not a sandbox: allowing a command that itself runs other commands (eval,bash,sh,source,xargs,timeout) effectively allows anything, so do not list those for untrusted/hosted use. denied_pathsrejects any command whose text references one of the given path substrings.
Usage example
from haystack.components.agents import Agent
from haystack.components.generators.chat import OpenAIChatGenerator
from haystack.dataclasses import ChatMessage
from haystack_integrations.tools.mirage import MirageWorkspace, MirageMount, MirageShellTool
workspace = MirageWorkspace([
MirageMount(path="/data", resource="ram"),
MirageMount(path="/s3", resource="s3", config={"bucket": "my-bucket"}, read_only=True),
])
tool = MirageShellTool(workspace, allowed_commands=["ls", "cat", "grep", "head", "wc", "cp"])
agent = Agent(chat_generator=OpenAIChatGenerator(model="gpt-4o-mini"), tools=[tool])
result = agent.run(messages=[ChatMessage.from_user("How many lines in /s3/log.txt mention 'alert'?")])
print(result["messages"][-1].text)
init
__init__(
workspace: MirageWorkspace,
*,
name: str = "mirage_shell",
description: str | None = None,
invocation_timeout: float = 60.0,
max_output_chars: int = 20000,
allowed_commands: list[str] | None = None,
denied_paths: list[str] | None = None
) -> None
Initialize the Mirage shell tool.
Parameters:
- workspace (
MirageWorkspace) – The :class:MirageWorkspacedescribing the mount tree. - name (
str) – Tool name exposed to the LLM. - description (
str | None) – Custom description. If None, one is generated from the mount tree. - invocation_timeout (
float) – Maximum seconds to wait for a command to finish. - max_output_chars (
int) – Truncate command output to this many characters before returning it. - allowed_commands (
list[str] | None) – If set, only these command names may run, e.g.["ls", "cat", "grep", "head", "wc"]. The allowlist is enforced against every command Mirage would execute -- including commands nested in substitutions/subshells -- sols "$(rm x)"is rejected unlessrmis also allowed. It is a filter over Mirage's virtual commands to steer the Agent, not a security sandbox; the write boundary is per-mountread_only(see the class "Security model" section). If None, any command is allowed (not recommended for untrusted/hosted use). - denied_paths (
list[str] | None) – If set, any command referencing one of these path substrings is rejected.
warm_up
Build the underlying live workspace eagerly. Called by Agent.warm_up()/Pipeline.warm_up().
to_dict
Serialize the tool to a dictionary in the {"type": ..., "data": ...} format.
from_dict
Deserialize the tool from a dictionary.
close
Close the underlying workspace.
haystack_integrations.tools.mirage.workspace
MirageMount
Declarative description of a single backend mounted into a :class:MirageWorkspace.
A mount is the serializable unit of a Mirage workspace: it names where a backend is mounted
(path), which backend it is (resource, a Mirage registry name such as "s3" or "gdrive"),
and how to configure it (config).
config values may be plain values, Haystack Secret objects for credentials, or an OAuth token
source (e.g. OAuthRefreshTokenSource) for backends whose config accepts a token-provider callable
(such as Mirage's OneDrive access_token). Secrets and token sources are resolved only when the
live workspace is built.
Every backend is created the same way. Use the Mirage registry name and the config keys that backend expects
(discover names with MirageMount.available_resources(); config keys come from the backend's Mirage config class):
from haystack.utils import Secret
MirageMount(path="/data", resource="ram") # in-memory scratch
MirageMount(path="/local", resource="disk", config={"root": "/srv/data"}) # local disk
MirageMount(path="/s3", resource="s3", config={"bucket": "my-bucket"}, read_only=True)
MirageMount(
path="/drive",
resource="gdrive",
config={"client_id": "...", "refresh_token": Secret.from_env_var("GDRIVE_REFRESH_TOKEN")},
read_only=True,
)
Parameters:
- path (
str) – Mount point in the virtual filesystem, e.g."/s3". - resource (
str) – Mirage registry name of the backend, e.g."ram","disk","s3","gdrive". Seemirage.resource.registry.REGISTRYorMirageMount.available_resources()for the full list. - config (
dict[str, Any]) – Keyword arguments passed to the backend's Mirage config. Values may beSecrets, or an OAuth token source that is turned into a token-provider callable when the workspace is built. - read_only (
bool) – If True, the mount is mounted in Mirage's READ mode and writes are rejected by Mirage itself.
available_resources
Return the Mirage registry names usable as resource.
These are short backend names such as "s3", "gdrive", "postgres". Pass one to
MirageMount(resource=...); the config keys each backend expects come from its Mirage
config class.
MirageWorkspace
A description of a Mirage mount tree that lazily builds a live mirage.Workspace.
MirageWorkspace is the shared backend behind the Mirage tools and components: it holds the list of
:class:MirageMounts and the cache configuration, serializes cleanly (resolving Secrets only at
build time), and constructs the live workspace on first use via Mirage's resource registry.
Usage example
from haystack.utils import Secret
from haystack_integrations.tools.mirage import MirageWorkspace, MirageMount
ws = MirageWorkspace(
mounts=[
MirageMount(path="/data", resource="ram"),
MirageMount(path="/s3", resource="s3", config={"bucket": "my-bucket"}, read_only=True),
]
)
print(ws.run("ls /s3"))
init
__init__(
mounts: list[MirageMount], *, cache_limit: str | int = "512MB"
) -> None
Initialize the workspace description.
Parameters:
- mounts (
list[MirageMount]) – The backends to mount, as a list of :class:MirageMount. - cache_limit (
str | int) – Mirage file-cache size limit (e.g."512MB"or an int byte count).
Raises:
MirageConfigError– If no mounts are provided or mount paths are not unique.
warm_up
Build the live mirage.Workspace eagerly. Idempotent.
close
Close the live workspace and release its resources, if it was built. Thread-safe.
run
run(
command: str, *, timeout: float = 60.0, max_chars: int | None = None
) -> str
Run a bash command against the mount tree from a synchronous context and return its output.
Parameters:
- command (
str) – A bash command line, e.g."grep -r alert /s3/logs | wc -l". - timeout (
float) – Maximum seconds to wait for the command. - max_chars (
int | None) – If set, truncate the returned text to this many characters.
Returns:
str– Combined stdout (plus a trailing error note on non-zero exit) as a string.
run_async
run_async(
command: str, *, timeout: float = 60.0, max_chars: int | None = None
) -> str
Async counterpart of :meth:run.
to_dict
Serialize the workspace description to a dictionary (Secret-safe).
from_dict
Deserialize a workspace description from a dictionary.
describe
Return a human/LLM-readable summary of the mount tree (used in tool descriptions).