ScopeLock is a reusable GenLayer authorization primitive for autonomous agents. It converts an owner's natural-language operating policy into a short-lived, replay-resistant capability permit that an integrated executor can consume.
- Network: GenLayer Bradbury Testnet
- Contract:
0xBDFd40F9C199d2D8505202D85F2851E8FB5ADa23 - Explorer: https://explorer-bradbury.genlayer.com/address/0xBDFd40F9C199d2D8505202D85F2851E8FB5ADa23
- Deployed source:
ScopeLock.py
The tracked Python file in this repository is the source used for the deployed contract above.
The contract separates two kinds of control:
- deterministic constraints, such as identity, amount ceiling, expiry, use count, and revocation;
- semantic constraints, such as whether an action actually matches the owner's intent and permitted purpose.
Deterministic rules run as ordinary contract code. GenLayer consensus is used only for the semantic boundary that deterministic smart contracts cannot interpret.
An agent may satisfy a JSON schema while violating the user's purpose. For example, a policy may permit buying one developer tool but not a subscription, financial asset, credential transfer, or a semantically equivalent workaround.
ScopeLock gives agent runtimes and smart-account executors a neutral authorization receipt instead of trusting one model or one agent operator.
A successful consensus decision creates an active permit containing:
- a SHA-256 commitment to the exact requested action;
- the only executor allowed to consume it;
- issue and expiry timestamps;
- a deterministic remaining-use counter;
- revocation state.
The registered executor calls consume_permit with the exact action hash immediately before executing the external action. A changed action, wrong executor, revoked policy, expired permit, or replay beyond the use limit is rejected deterministically.
The evaluator returns:
ALLOW: the action clearly fits both user intent and allowed scope;DENY: it violates, exceeds, evades, or conflicts with policy or intent;NEEDS_OWNER: a material ambiguity requires new owner authority.
The leader proposes a structured decision. Validators independently verify that the controlling rule exists, the result follows the policy, and the explanation does not invent authority.
NEEDS_OWNER is an explicit state, not a vague failure. The policy owner can approve or deny it through owner_decide without pretending that validators resolved an ambiguity they could not defensibly resolve.
create_policy(
title,
agent,
executor,
allowed_scope,
forbidden_scope,
max_amount,
permit_ttl_seconds,
max_uses
)
request_permit(policy_id, action_type, target, amount, details, user_intent)
evaluate_permit(request_id)
owner_decide(request_id, allow)
consume_permit(request_id, action_hash)
revoke_permit(request_id)
revoke_policy(policy_id)
get_policy(policy_id)
get_request(request_id)
get_stats()
Deploy ScopeLock.py. For the simplest Studio test, use your current wallet address as both agent and executor.
Call create_policy with:
title:
Developer tooling buyer
agent:
<YOUR WALLET ADDRESS>
executor:
<YOUR WALLET ADDRESS>
allowed_scope:
May purchase a one-time developer tool or public technical documentation explicitly requested by the owner. The purchase must not renew automatically.
forbidden_scope:
Must not buy financial assets, create subscriptions, transfer funds to the agent, disclose credentials, or delegate authority to another party.
max_amount:
1000
permit_ttl_seconds:
3600
max_uses:
1
Then call request_permit:
policy_id: 1
action_type: purchase
target: docs.vendor.example/basic-license
amount: 250
details: Buy one non-renewing developer documentation license. No subscription and no credential sharing.
user_intent: Purchase the basic documentation license once for this project.
Call evaluate_permit(1). A well-grounded result should be ALLOW.
Copy action_hash from the returned request and call:
consume_permit(1, <ACTION_HASH>)
The request should become CONSUMED because the policy allowed one use.
Create a second request under the same policy:
policy_id: 1
action_type: asset_trade
target: crypto.exchange/BTC
amount: 250
details: Buy BTC and hold it for the owner.
user_intent: Increase the owner's investment holdings.
Call evaluate_permit(2). The expected result is DENY because purchasing financial assets is explicitly forbidden even though the amount is below the numeric ceiling.
ScopeLock cannot stop an agent from using an unrelated executor that ignores the contract. It is designed for smart accounts, agent runtimes, tools, and settlement contracts that require a valid ScopeLock permit before execution.
The amount unit is defined by the integrating executor. ScopeLock compares the integer deterministically but does not transfer funds itself.
ScopeLock.py is self-contained and can be pasted directly into GenLayer Studio.