Skip to content

spanforge.sdk.scope

Runtime scope enforcement for agent capabilities and resource access.

SFScopeClient

from spanforge.sdk import sf_scope

ACTION_CATEGORIES

from spanforge.sdk.scope import ACTION_CATEGORIES

Module-level dict mapping five canonical category names to frozensets of action strings:

CategoryActions
readread, list, get, describe, view, query, fetch, download
writewrite, create, update, delete, patch, put, append, insert, remove
executeexecute, run, invoke, trigger, call, dispatch, submit
adminadmin, configure, deploy, restart, scale, shutdown, grant, revoke, manage
streamstream, subscribe, publish, consume, emit, broadcast

Use resolve_action_category(action) to look up a category by action name.

Circuit Breaker

SFScopeClient.__init__() accepts two new parameters (1.0.1):

ParameterTypeDefaultDescription
cb_thresholdint5Number of consecutive emit failures before the circuit opens.
cb_reset_secondsfloat30.0Seconds before the circuit automatically resets to closed.

When the circuit is open, evaluate() returns allowed=False with outcome="block" and reason="circuit breaker is open; failing secure" immediately — no manifest lookup, no network call.

Workflow

  1. Register an agent manifest with allowed capabilities and resource actions.
  2. Evaluate requested runtime actions.
  3. Emit signed scope decision records.

register_agent(...)

sf_scope.register_agent(
    agent_id="claims-agent",
    capabilities=["claim.read", "decision.write"],
    resource_actions={"claims": ["read"], "decisions": ["write"]},
)

evaluate(...)

Checks whether an agent may perform a resource action. Returns a fail-secure block decision immediately when the circuit breaker is open.

evaluate_with_policy(...)

Runs the scope check and attaches the active policy decision metadata.

resolve_action_category(action: str) -> str | None

Static method. Returns the category name ("read", "write", "execute", "admin", or "stream") for a given action string, or None if the action is not in any category.

from spanforge.sdk.scope import SFScopeClient

SFScopeClient.resolve_action_category("read")    # "read"
SFScopeClient.resolve_action_category("deploy")  # "admin"
SFScopeClient.resolve_action_category("unknown") # None

list_for_trace(trace_id)

Returns all scope decisions recorded for a trace.

Outcomes

The emitted scope decision outcome is one of:

  • allow
  • block (also returned by circuit-breaker fast path)
  • redact
  • human_review
  • escalate

Signed records are written under:

spanforge.scope.v1


ScopeStatusInfo dataclass

Returned by sf_scope.get_status().

FieldTypeDescription
statusstr"ok" when the service is healthy.
registered_agentsintNumber of agents with registered manifests.
total_checksintTotal evaluate() calls since startup.
blocked_checksintChecks that returned allowed=False.

get_status() -> ScopeStatusInfo

info = sf_scope.get_status()
print(info.registered_agents)  # e.g. 3
print(info.total_checks)        # e.g. 148

ScopeManifest dataclass

Stored per-agent by register_agent() and load_manifest_from_yaml().

FieldTypeDescription
agent_idstrUnique agent identifier (non-empty).
capabilitieslist[str]Declared capability tokens, e.g. ["tool.read", "tool.execute"].
resource_actionsdict[str, list[str]]Per-resource allowed actions; "*" key is the wildcard catch-all.
metadatadict[str, Any]Arbitrary manifest metadata (team, version, etc.).