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.
Run before the capability executes. This is the most important policy stage.
Timing
A before_capability policy runs after the call is intercepted but before the underlying function executes. If the policy denies, CapabilityDeniedError is raised and the function never runs. The consequence does not occur.
agent calls capability
-> Brane intercepts
-> AgentAction created
-> PolicyContext built
-> before_capability policies run
-> allow: function executes
-> deny: CapabilityDeniedError raised, function does not run
Registration
@runtime.before_capability("capability_name")
def my_policy(ctx):
return Decision(type="allow")
What Is Available
In a before_capability policy, ctx.output is always None; the function has not run yet.
ctx.capability
ctx.arg("name")
ctx.agent_id, ctx.principal_id, ctx.tenant_id
ctx.is_prod, ctx.is_high_risk
ctx.agent_has_scope("scope")
Common Use Cases
Block unsafe SQL input:
@runtime.before_capability("execute_sql")
def read_only_sql(ctx):
query = ctx.arg("query", "").lower().strip()
if not query.startswith("select"):
return Decision(type="deny", reason="Only SELECT queries are allowed")
return Decision(type="allow")
Block high-risk tools in production:
@runtime.before_capability("*")
def block_high_risk_in_prod(ctx):
if ctx.is_prod and ctx.is_high_risk:
return Decision(
type="deny",
reason="High-risk capability use requires an approved workflow in prod",
)
return Decision(type="allow")
Enforce a financial limit:
@runtime.before_capability("refund_customer")
def refund_amount_limit(ctx):
amount = ctx.arg("amount_usd", 0)
limit = get_tenant_limit(ctx.tenant_id)
if amount > limit:
return Decision(type="deny", reason=f"Refund ${amount} exceeds limit of ${limit}")
return Decision(type="allow")
Check scopes:
@runtime.before_capability("refund_customer")
def require_refund_scope(ctx):
if not ctx.agent_has_scope("refunds:create"):
return Decision(type="deny", reason="Agent requires refunds:create scope")
return Decision(type="allow")
Deny Behavior
When any before policy returns Decision(type="deny"):
- The runtime stops evaluating remaining before policies
- The underlying function is not called
CapabilityDeniedError is raised with the denial reason
from brane import CapabilityDeniedError
try:
execute_sql("delete from customers")
except CapabilityDeniedError as e:
print(e.reason)
print(e.policy_name)
print(e.action_id)
Policy Order
Multiple before policies on the same capability run in descending priority order. Deny wins: if any policy denies, the action is blocked regardless of other policies.
Wildcard policies ("*") run alongside exact-match policies.
Future Decision Types
approval_required: pause until a human approves
transform_input: mutate the input before execution
route: redirect to a different capability or provider
sandbox: execute with restricted access
log_only: allow but flag for review