One owner, scoped grants, narrowing only
Every space has one owner. Sharing it means issuing a grant to another agent with a set of rights and a persistence mode. Rights can only narrow from what the owner chose to offer on the space (its defaultRights, all 15 content rights when left out), so a grantee can never end up with more than the owner intended, and can never pass on more than it holds. A right outside that ceiling is dropped silently: the grant still answers ok, and effectiveRights shows what survived. The ceiling cannot be changed after the space is created. The worldMutation ladder is separate from content rights, which is what lets an owner allow reading without allowing changes.
# owner: share one space with another agent (its agent id from register) grant = owner.grant_access(space.space_id, worker_agent_id, rights=["read", "quote"]) # the grantee reads with its own session; fetch checks the grant on every call, # so a session opened before the grant works too worker.connect() print(worker.fetch(space.space_id, query="refund").contents()) # immediate, forward-only owner.revoke_access(grant.capability_ref)
When the consumer asks first
A consumer that discovers a public or unlisted space can ask for access with a reason. The owner sees pending requests, approves with the rights it is comfortable with (narrowing if it wants), or denies. The consumer can then fetch the space at once; fetch checks the grant on every call. Until the owner approves, a requester sees at most the metadata discover lists for public spaces (name, owner, offered rights, size, pricing), never the stored content.
# consumer: ask for access to a space it can discover
consumer.request_access(space_id, rights=["read"], reason="needs the rate limit")
# owner: review and decide
for req in owner.list_requests():
owner.approve_request(req["id"], rights=["read"]) # or owner.deny_request(req["id"])Revocation is immediate and forward-only
revoke retires a grant for every future call. It does not rewrite history: receipts already issued stay valid, which is what an audit needs. To confirm a revoke took effect, trust its result or let the revoked agent try; it is denied.
A preflight exists too: check_rights answers whether the calling agent would be allowed an operation, and at what price under the space's price schedule (including whether the read falls inside that schedule's included allowance), without performing it.
What the receipt gives both sides
Metered reads return a receipt id. The owner can see which agent read which space and when; the consumer can verify what it was served. That record is the difference between two teams trusting a shared memory and two teams trading exports by email.
from priostack import ACNClient # pip install priostack
with ACNClient() as acn: # https://priostack.com/mcp
acn.register(display_name="my-agent") # token captured, shown once
acn.connect() # session id captured
space = acn.create_space("prod-memory")
acn.store(space.space_id, objects=[
{"content": "Refunds over $500 need manager approval.", "type": "declaration"},
{"content": "Export latency was 1.8s at 14:02 UTC.", "type": "observation"},
])
for c in acn.fetch(space.space_id, query="refund").contents():
print(c)Questions people ask
Can two companies share a space?
Yes. Accounts are isolated; a grant is the only bridge between them, it carries exactly the rights the owner chose, and it can be revoked at any time.
What happens to the grantee's session after a revoke?
Its next call on that space is denied. A new grant works for fetch at once, and a session picks up the widened scope for the other reads when it connects again; after a revoke, the space is simply no longer readable.
Is context copied to the grantee?
No. The grantee reads the owner's space in place, within its rights; the owner keeps the single source of truth.