Test a grant change first
Drop or add a grant in a copy of the policy, probe it, and read each verdict before and after the change.
drills.counterfactual
Drop or add a grant in a copy of the policy, probe it, and read each verdict before and after the change.
drills.counterfactualPut admission in front of your MCP servers, repositories, SaaS tools and cloud accounts. Every agent gets a lease or a reason – and you keep the lever to stop any of them.
You are about to remove a grant and want to know which agent loses what. Intralock evaluates each probe against the policy as it stands and against a copy with your change applied. No model runs, and nothing in the workspace changes.
policies.propose the narrowest permission the doc names for this steppolicies.propose permission, which running a drill needsThe code reads the key from INTRAMEDIAL_KEY. Keep it in your shell or your secret store, never in a file you commit. Calls that need a signed-in person cannot use a key: the console makes them.
pack_counterfactual is built in. It drops the grant g-house and probes did:a reading repo:main, so you see the response shape before you write your own. With a drill workflow bound and no forceInline, the answer is queued: true with a workflowId.
drills.counterfactualdrills-counterfactual
curl -sS -X POST https://api.intramedial.com/api/v1/acp/drills/counterfactual \
-H "Authorization: Bearer $INTRAMEDIAL_KEY" \
-H "Content-Type: application/json" \
-d '{
"packId": "pack_counterfactual"
}'const res = await fetch("https://api.intramedial.com/api/v1/acp/drills/counterfactual", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.INTRAMEDIAL_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
packId: "pack_counterfactual",
}),
});
console.log(res.status, await res.json());import os, requests
res = requests.post(
"https://api.intramedial.com/api/v1/acp/drills/counterfactual",
headers={"Authorization": "Bearer " + os.environ["INTRAMEDIAL_KEY"]},
json={
"packId": "pack_counterfactual",
},
timeout=30,
)
print(res.status_code, res.json())Each probe has a before and an after. An allow names its grantId; a deny gives a reason such as no_grant or cycle, and a detail. before and after describe the first probe.
{
"packId": "pack_counterfactual",
"dropped": "g-house",
"droppedIds": ["g-house"],
"added": [],
"probes": [
{
"probe": { "principal": "did:a", "resource": "repo:main", "action": "read", "nowMs": 1793523600000 },
"before": { "allow": true, "grantId": "g-house", "protectedClass": "none" },
"after": { "allow": false, "reason": "no_grant", "detail": "did:a lacks read on repo:main" }
}
],
"llm": false
}Send grantIds to drop, or addGrants for hypothetical grants, and the probes that matter. A hypothetical grant that would form a cycle is skipped, not applied.
curl -sS -X POST https://api.intramedial.com/api/v1/acp/drills/counterfactual \
-H "Authorization: Bearer $INTRAMEDIAL_KEY" \
-H "Content-Type: application/json" \
-d '{
"grantIds": [
"g-house"
],
"probes": [
{
"actorDid": "did:web:acme.example:agent:billing",
"resource": "repo:payments/main",
"action": "write"
}
]
}'const res = await fetch("https://api.intramedial.com/api/v1/acp/drills/counterfactual", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.INTRAMEDIAL_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
grantIds: ["g-house"],
probes: [
{
actorDid: "did:web:acme.example:agent:billing",
resource: "repo:payments/main",
action: "write",
},
],
}),
});
console.log(res.status, await res.json());import os, requests
res = requests.post(
"https://api.intramedial.com/api/v1/acp/drills/counterfactual",
headers={"Authorization": "Bearer " + os.environ["INTRAMEDIAL_KEY"]},
json={
"grantIds": ["g-house"],
"probes": [
{
"actorDid": "did:web:acme.example:agent:billing",
"resource": "repo:payments/main",
"action": "write",
},
],
},
timeout=30,
)
print(res.status_code, res.json())Copied from: /docs/drills-counterfactual
The ledger is append-only and sealed under Merkle roots. The time on an entry is Intramedial's own clock, and a signed bundle can be checked offline with the published key.
Compile a mandate with apply: false, read the grants it would make and its previewDigest, then apply exactly what you previewed.
mandates.compileRun the six fixed Intralock scenarios, read the result of each one, and set a cadence so the drill repeats on its own.
drills.frtRun an installed lens over the data you send, read its findings and keep the stored result with its digest.
lenses.runOne short email when we add recipes to the cookbook. No other mail, and you can unsubscribe from any message.
No key or account: Try it on the coordination.admit module page runs the real kernel in your browser. Use a workspace key for your own workspace.