> ## Documentation Index
> Fetch the complete documentation index at: https://docs.plyra.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Protect your first tool call in 60 seconds

## Install

<CodeGroup>
  ```bash pip theme={null}
  pip install plyra-guard
  ```

  ```bash uv theme={null}
  uv add plyra-guard
  ```
</CodeGroup>

## Protect a tool

```python theme={null}
from plyra_guard import ActionGuard, RiskLevel

guard = ActionGuard.default()

@guard.protect("file.delete", risk_level=RiskLevel.HIGH)
def delete_file(path: str) -> str:
    import os
    os.remove(path)
    return f"Deleted {path}"
```

When the agent calls `delete_file`, plyra-guard intercepts first:

```python theme={null}
delete_file("/tmp/report.txt")   # Verdict: ALLOW — executes normally
delete_file("/etc/passwd")       # Verdict: BLOCK — ExecutionBlockedError raised
```

<Note>
  `ExecutionBlockedError` carries three fields that explain exactly what
  happened: `what_happened`, `policy_triggered`, and `how_to_fix`.
  Catch it to handle blocks gracefully in your agent loop.
</Note>

## Handle blocked calls

```python theme={null}
from plyra_guard.exceptions import ExecutionBlockedError, ActionEscalatedError

try:
    delete_file("/etc/passwd")
except ExecutionBlockedError as e:
    print(e.what_happened)      # "File path matches block rule: system config"
    print(e.policy_triggered)   # "block-system-config"
    print(e.how_to_fix)         # "Use a path under /tmp/ or update your policy"
except ActionEscalatedError as e:
    print(e.reason)             # Why escalation was triggered
    print(e.escalate_to)        # Where the escalation was routed
```

Both exceptions carry structured context. Your agent loop should catch them
and decide whether to retry with a different approach, surface to the user,
or abort the task.

````

## Load a policy file

Create `guard_config.yaml` in your project root:

```yaml
version: "1.0"

global:
  default_verdict: BLOCK

policies:
  - name: block-env-files
    action_types: ["*"]
    condition: '".env" in parameters.get("path", "")'
    verdict: BLOCK
    message: "No .env access"

  - name: block-system-config
    action_types: ["*"]
    condition: 'parameters.get("path", "").startswith("/etc/")'
    verdict: BLOCK
    message: "System config is off-limits"

  - name: allow-tmp
    action_types: ["*"]
    condition: 'parameters.get("path", "").startswith("/tmp/")'
    verdict: ALLOW

  - name: escalate-schema-changes
    action_types: ["*"]
    condition: '"DROP TABLE" in str(parameters)'
    verdict: ESCALATE
    message: "Schema changes require human approval"
````

```python theme={null}
guard = ActionGuard.from_config("guard_config.yaml")
```

## Wrap a list of tools

```python theme={null}
safe_tools = guard.wrap([read_file, write_file, delete_file])
```

Pass `safe_tools` to any framework that accepts a tool list.

## Launch the dashboard

```bash theme={null}
pip install "plyra-guard[sidecar]"
plyra-guard serve
# → http://localhost:8765
```

<CardGroup cols={2}>
  <Card title="Policy reference" href="/guard/policy" icon="file-code">
    Learn the full rule syntax.
  </Card>

  <Card title="Framework integrations" href="/guard/frameworks" icon="plug">
    LangGraph, AutoGen, CrewAI, and more.
  </Card>
</CardGroup>
