Docs/Core Concepts

Core Concepts

PermitNetworks is built on a small number of composable primitives. Understanding these will make the rest of the documentation — policies, API, SDKs — click into place.

How it fits together

Agent→ authorize(action, resource) →Policy Engine→ Decision→ Permit (signed token)→ Audit Log

Agents

An agent is any autonomous process that takes actions on behalf of a user or system. In PermitNetworks, agents are the primary principals — the entities that request authorization. Every agent has a unique string identifier (e.g. "billing-bot", "support-agent-prod") that you assign when initializing the SDK.

Agents are registered automatically on first use. You can attach metadata to agents — tags, descriptions, owner contact — through the dashboard or the API. An agent's history of decisions is queryable through the audit log filtered by agent_id.

In multi-agent systems, each agent should have its own ID and its own set of policies. Do not share a single agent ID across processes that have different authorization requirements — granularity here is what enables meaningful audit trails.

Actions

Actions are the semantic verbs that describe what an agent wants to do. They follow a dot-notation pattern: namespace.verb (e.g. payment.create, data.read, file.delete, email.send). The namespace groups related actions and can be used in policy wildcards.

Actions are free-form strings — PermitNetworks does not have a fixed action registry. You define the actions that make sense for your domain. However, we recommend following the namespace.verb convention for consistency and to enable wildcard matching in policies.

Common namespaces include: data (read, write, delete, export), payment (create, refund, approve), agent (spawn, stop, configure), and file (read, write, execute). Use specific verbs rather than generic ones — "payment.create" is more auditable than "payment.do".

Resources

A resource is the thing being acted upon. Resources are identified by a string that typically encodes the resource type and its identifier, separated by a colon: user:123, account:acct_9kx2m, document:doc_legal_2025_03.

Resources can be specific (user:123) or refer to a class of objects (user:*). Policy rules can match on exact resource IDs, wildcard patterns, or regex expressions. When you call permit.authorize(), the resource you pass is matched against the patterns defined in your policies.

Resources are optional in the authorization request — if omitted, the policy evaluates the action alone. Use resources when the authorization decision depends on which specific object is being accessed, not just the type of operation.

Policies

Policies are the rules that govern what agents can and cannot do. Each policy is a JSON document with a name, a priority, an optional list of target agents, and one or more rules. Rules specify an action pattern, a resource pattern, an effect (allow or deny), and optional conditions.

Policies are evaluated in priority order — lowest priority number first. The first rule whose action and resource patterns match the request determines the outcome. If no policy matches, the default effect is deny. This deny-by-default posture is intentional: every action must be explicitly allowed.

Policies support four effects: allow (proceed), deny (block), review (allow but flag for human review), and log (allow but record for audit without enforcement). Rate limits and budget constraints are also defined at the policy level and are evaluated alongside rule conditions.

Decisions

A decision is the output of evaluating an authorization request against your policies. Each decision has a unique ID, an effect (allow/deny/review/log), a reference to the matched policy, and metadata about latency and evaluation time. Decisions are immutable once created.

The decision lifecycle has three states: pending (created, waiting for confirmation), confirmed (the agent reported the action completed), and rejected (the agent reported the action was aborted or failed). Calling permit.confirm() or permit.reject() moves the decision out of pending state.

Every decision is written to the append-only audit log and assigned a position in the Merkle tree. This means any decision can be independently verified by a third party using the proof endpoint — the audit record cannot be altered without breaking the cryptographic chain.

Permits

A permit is a signed token that proves a specific action was authorized by PermitNetworks at a specific time. When a decision has effect allow, the response optionally includes a permit token — a compact, self-contained proof that can be passed to downstream services.

Permits are Ed25519-signed JWTs that encode the decision ID, agent ID, action, resource, and expiry. Downstream services can verify a permit offline without calling the PermitNetworks API — they just need the public key, which is published at /.well-known/jwks.json.

Permits expire. The TTL is configurable per-policy (default: 5 minutes). If the downstream service receives a permit after its expiry, it must reject it and the agent must request a new authorization. This short TTL is intentional: it limits the blast radius of a compromised permit.

Audit Log

The audit log is an immutable, append-only record of every authorization decision ever made in your account. Each entry records the full context of the decision: who (agent), what (action + resource), when (timestamp), why (policy matched), and the outcome (allow/deny/review).

The audit log is organized as a Merkle tree. Each new decision is hashed together with the previous decision's hash, forming a chain. This means you can request a Merkle proof for any specific decision and verify, mathematically, that the record has not been tampered with since it was created.

You can query the audit log through the dashboard or the API with filters on agent, action, outcome, and time range. Audit log export (CSV, JSON, SIEM webhook) is available for compliance reporting.

Budget

Budget limits constrain how much an agent can spend — in fiat currency, API calls, or any numeric unit — within a rolling time window. Budgets are defined in policies and enforced at decision time: if a decision would cause the agent to exceed its budget, the effect is automatically overridden to deny.

PermitNetworks tracks budget consumption in real time. When an action is confirmed (via permit.confirm()), the budget counter is incremented by the amount in the decision context. Rejected decisions do not consume budget. Budgets reset at the start of each period (hourly, daily, monthly).

Budget thresholds trigger webhooks. You can configure alerts at 75% and 90% of budget consumption so your team can react before the limit is hit. When the limit is exceeded, a budget.exceeded webhook fires and all subsequent decisions for that agent are automatically denied until the next period.

Scopes

Scopes define what an API key is allowed to do — not what your agents are allowed to do (that is policies' job), but what actions the holder of the API key can perform against the PermitNetworks API itself. Scopes follow an allow-list model.

When you create an API key, you grant it a set of scopes. Common scopes include decisions:write (submit authorization requests), policies:read (fetch policies), audit:read (query the audit log), and webhooks:manage (configure webhook endpoints). Keys used in production agents typically need only decisions:write.

Principle of least privilege applies: a key used in a read-only analytics service should not have decisions:write scope. You can rotate keys without downtime by creating a new key, updating your deployment, and revoking the old key — the SDK retries on 401 if you configure a secondary key.