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

# Quickstart

> Install brane-core and govern your first tool capability.

Install `brane-core` and govern your first tool capability.

## Install

```bash theme={null}
pip install brane-core
```

<Note>
  Package name may change before the stable release. Check the GitHub repo for the latest install instructions.
</Note>

## Create a Runtime

A [Runtime](/sdk/runtime) is the coordinator for capabilities and policies. Create one per agent process.

```python theme={null}
from brane import Decision, Runtime

runtime = Runtime(agent_id="data-agent", environment="dev")
```

## Register a Capability

Use the `@runtime.capability` decorator to turn a function into a governed capability. The decorator registers the capability in the runtime's capability registry and wraps the function so every call passes through the policy engine.

```python theme={null}
@runtime.capability(name="execute_sql", type="tool", risk="high")
def execute_sql(query: str):
    return {"rows": []}
```

## Write a Before Policy

A [before\_capability](/policy/before-capability) policy runs before the function executes. Return `Decision(type="deny")` to block the action. Return `Decision(type="allow")` to let it proceed.

```python theme={null}
@runtime.before_capability("execute_sql")
def read_only_sql(ctx):
    if not ctx.arg("query").lower().strip().startswith("select"):
        return Decision(type="deny", reason="Only SELECT queries are allowed")
    return Decision(type="allow")
```

## Call the Capability

```python theme={null}
# Allowed: query starts with SELECT
result = execute_sql("select * from customers limit 10")
# Returns: {"rows": []}

# Denied: query starts with DELETE
execute_sql("delete from customers")
# Raises: CapabilityDeniedError: Only SELECT queries are allowed
```

## Handle the Error

```python theme={null}
from brane import CapabilityDeniedError

try:
    execute_sql("delete from customers")
except CapabilityDeniedError as e:
    print(f"Blocked: {e.reason}")
    print(f"Policy: {e.policy_name}")
    print(f"Action ID: {e.action_id}")
```

## What Happened

When you called `execute_sql("delete from customers")`, Brane:

1. Intercepted the function call
2. Created an [AgentAction](/concepts/agent-action) record for the attempt
3. Built a [PolicyContext](/concepts/policy-context) with the capability, arguments, and runtime metadata
4. Found the `read_only_sql` policy matching the `execute_sql` capability
5. Evaluated the policy; it returned `Decision(type="deny")`
6. Raised `CapabilityDeniedError` without calling the underlying function

## Complete Example

```python theme={null}
from brane import CapabilityDeniedError, Decision, Runtime

runtime = Runtime(agent_id="data-agent", environment="dev")

@runtime.capability(name="execute_sql", type="tool", risk="high")
def execute_sql(query: str):
    return {"rows": []}

@runtime.before_capability("execute_sql")
def read_only_sql(ctx):
    if not ctx.arg("query").lower().strip().startswith("select"):
        return Decision(type="deny", reason="Only SELECT queries are allowed")
    return Decision(type="allow")

# Allowed
result = execute_sql("select 1")
print(result)  # {"rows": []}

# Denied
try:
    execute_sql("delete from customers")
except CapabilityDeniedError as e:
    print(f"Blocked: {e.reason}")
```

## Next Steps

* [Mental Model](/concepts/mental-model)
* [Capability](/concepts/capability)
* [Writing Policies](/policy/writing-policies)
* [After Capability](/policy/after-capability)
* [SQL Read-Only Recipe](/recipes/sql-read-only)
