Private applications need to treat an AI agent as a narrowly authorized operator, not as a second owner of the user’s wallet, credentials or private state.

On August 19, Midnight Foundation President Fahmi Syed warned that it is frightening to hand a single AI agent unrestricted access to personal information, financial data and multiple accounts without clear parameters. His point, reported by The Block during the Wyoming Blockchain Symposium, turns an abstract concern about agent safety into a concrete engineering question for private applications: what exactly is an agent allowed to do, for whom, under what conditions, and for how long?

For Midnight applications, the answer cannot simply be, “the agent can prove private facts.” A zero knowledge proof can establish that a condition holds while keeping its underlying witness confidential. It cannot decide whether an agent should have been permitted to act in the first place.

That distinction matters because an agent can be dangerous even when every cryptographic operation is valid. A compromised agent may submit an authorized transaction at the wrong time. A hallucinating agent may choose the wrong counterparty. A malicious agent operator may repeatedly invoke a broad permission that the user granted for what seemed like a benign task. Privacy protects information. Authority constrains action. A secure delegated system needs both.

The useful objective is not to make an agent powerful enough to run a user’s financial life. It is to let an agent complete one useful task inside a small, inspectable permission envelope. The user should be able to say, in effect: “You may perform this type of action, against this application and this counterparty, before this time, for no more than this amount, at most this many times, if this private condition is satisfied.” Everything outside that sentence should remain unavailable.

That is a protocol design problem.

The dangerous shortcut: treating credentials as delegation

The easiest way to build an agentic application is also usually the wrong way. A user supplies a wallet seed, a broad signing key, a reusable viewing key, or raw private state to an agent. The agent then has enough access to inspect balances, generate proofs, select transactions and authorize calls.

This approach creates a single large blast radius.

A wallet seed can expose every asset and future action controlled by that wallet. An unrestricted signing key can turn every prompt injection, software exploit or operator compromise into an asset movement. A reusable viewing credential can reveal a history of private activity far beyond the transaction the agent needs to evaluate. A witness can expose balances, attributes, relationship data or application state that should never leave the user controlled environment.

These are not merely confidentiality failures. They are authority failures.

An application may correctly hide an account balance from a public chain observer, yet still give an agent the power to spend that balance. It may use zero knowledge to prove that a buyer is eligible for a private discount, while allowing the same agent to apply the credential repeatedly at unintended merchants. It may encrypt the user’s data in transit, while the agent service retains a durable copy after the task ends.

The secure default is therefore simple: an agent should receive neither a master secret nor a general purpose credential merely because it has been asked to automate something.

SEED PHRASE; SIGNING KEY; VIEWING KEY; FULL WITNESSNAMED ACTION; CONTRACT; COUNTERPARTY; CEILING; EXPIRY; NONCEWALLET TRUST BOUNDARYSEED PHRASE; SIGNING KEYALL STATE; ANY VALID CALLREUSABLE CREDENTIALNAMED ACTION; CONTRACTUSERWALLEToverprivilegeddelegationAI AGENTbroadreusableaccessMIDNIGHTAPPLICATIONprivateactionverifierCOUNTERPARTYunintendedmerchantUSERWALLETkeys andwitnessretainedCAPABILITYTOKENone boundedactionAI AGENTscoped taskexecutorBroad reusable power enables unintended reuse; narrow capabilities make delegation explicit
Figure 1 - how capability-scoped delegation lets an AI agent automate a private action without receiving reusable keys or the full witness

The comparison is not between automation and security. It is between broad reusable power and narrow consumable power. A well designed system can still be highly automated. It simply makes each form of automation explicit.

Privacy is not permission

Private systems often focus on a question such as: “Can the application verify that the user meets a condition without learning the sensitive data behind it?” That is an important question. It is not the whole question.

Consider a private credit application. A user wants an agent to rebalance collateral if a loan health ratio falls below a chosen threshold. The agent needs to know whether the threshold has been crossed. The lending application needs confidence that the action is valid. Neither party necessarily needs to see every holding, every transaction or the complete financial history that supports the calculation.

A private proof can establish a statement such as:

The user’s loan health ratio is below the configured threshold, and the proposed repayment does not exceed the user’s authorized ceiling.

The proof hides inputs such as balances, debt positions and perhaps the precise threshold. That is the confidentiality layer.

But a second question remains:

Is this particular agent currently authorized to make this particular repayment to this particular contract, using this user’s funds, under this limit?

That is the authority layer.

The two layers should be represented separately in both the protocol and the user interface. A proof answers whether a private condition is true. An authorization answers whether an actor may invoke an action because that condition is true.

PROVER-SIDE TRUST BOUNDARYPRIVATE WITNESSZERO-KNOWLEDGE PROOFACTION CONSTRAINTSPROVERholdsprivatewitnessPROOFGENERATORderivesprivate factVERIFIERchecks proofonlyAUTHORIZATIONconstrainedactioncredentialCONTRACTacceptsauthorizedactionThe witness stays private; only proof and constrained authority cross.
Figure 2 - how a proof reaches the verifier without the witness while authorization remains separate

The trust boundary in this model is not a decorative feature. It identifies what must not be delegated casually. The witness may include the private data required to establish a fact. The authorization credential should include only the constrained authority required to act on that fact. Neither should be mistaken for the other.

If an agent receives a witness, it may learn too much. If it receives a broad authorization, it may do too much. If it receives both, a compromise may reveal too much and do too much at once.

Start with a transaction intent, not an open ended instruction

An AI agent works best with natural language. Protocols work best with precise state transitions. A delegated private application must translate from one to the other.

“Keep my position safe” is a useful human goal, but it is not an authorization. It lacks a maximum spend, an approved destination, a time limit, an action type and a clear condition. It also gives a model too much room to interpret.

A transaction intent is the structured object that closes this gap. It should describe the action the user is willing to have performed, rather than a broad objective the agent is expected to optimize indefinitely.

For example, an intent could state:

Field Example constraint
Action Repay a private lending position
Application Only the specified lending contract
Counterparty Only the user’s own loan position
Asset Only the approved settlement asset
Spending ceiling Up to 500 units
Trigger A valid proof that the health condition is met
Expiry Valid until a specified time
Use limit One successful execution
Nonce A unique identifier bound to this intent
Disclosure Reveal only the required eligibility result

The user does not need to expose the entire position to form this intent. The application does not need an agent to hold a wallet seed in order to enforce it. The intent can be committed to a capability that is evaluated during the private application call.

The critical design choice is that the agent is not authorized to “manage the account.” It is authorized to submit a particular class of call whose parameters must fit the user’s constraints.

This structure also makes human approval practical. The user can review a compact summary before delegation:

  • Repay up to 500 units.
  • Only if the private risk condition is met.
  • Only for this loan.
  • Only once.
  • Expires tonight.
  • No balance history disclosed to the agent.

That is legible. “Grant agent wallet access” is not.

Capability scoped delegation: power that fits the task

A capability is a permission that conveys authority to perform a defined action. In a private application, a capability should be both narrow and binding. Narrow means it carries no powers unrelated to the task. Binding means it cannot be detached from its constraints and used somewhere else.

A useful capability scope has at least seven dimensions.

Action scope. Specify the exact entry point or action family. “Claim rebate” is different from “transfer assets.” “Submit a bid” is different from “change account settings.” A capability should not silently cover adjacent actions merely because they share a contract.

Application scope. Bind the capability to a particular Compact application or contract identity. The agent should not be able to replay the authorization on a lookalike application or redirect it to an unrelated protocol.

Counterparty scope. Bind the permitted recipient, merchant, loan position, seller, pool or credential verifier. Counterparty specific disclosure is especially important in private commerce. An agent authorized to prove eligibility to Merchant A should not turn that proof into a reusable credential at Merchant B.

Value scope. Set a maximum amount, quantity or risk budget. A spending ceiling limits damage even if the agent is compromised. The ceiling should be expressed in the relevant asset and, where appropriate, bounded by price, slippage or fee conditions.

Time scope. Set a start time and expiry. A useful authorization becomes dangerous when it lasts forever. Short validity windows reduce exposure to delayed execution, credential theft and changes in the user’s intent.

Use scope. Define whether the capability is single use, limited use or recurring under a defined schedule. A task that should happen once must not be represented by an indefinitely reusable permission.

Information scope. State what private result may be revealed, to whom, and for what purpose. A proof that says “eligible” can be safer than one that discloses a balance range, a location, an identity attribute or a transaction history.

Each restriction should be enforced by the application, not merely recorded in the agent’s prompt. Prompts are instructions. Capabilities are constraints.

DENIED BY APPLICATION: SEED EXPORT; UNRELATED TRANSFERS; OTHER COUNTERPARTIES; REPEAT EXECUTION; FULL TRANSACTION HISTORYDENIED BY APPLICATION: SEEDACTION SCOPEAPPLICATION BINDINGPOSITION IDENTIFIERVALUE CEILINGEXPIRY AND USE RULEPRIVATE PROOF CLAIMDELEGATEDCAPABILITYACTION:REPAY LOANAPPLICATIONLendingCompact appCOUNTERPARTYPosition4821VALUEMaximum 500unitsTIME ANDUSEExpires20:00 UTC;oneDISCLOSUREProve healthconditiononly
Figure 3 - how a delegated capability limits an agent to one private, bounded loan repayment

A capability does not need to disclose the full private data it protects. The application can verify that the proposed call fits the capability and that a suitable private condition has been proven. The agent only needs enough information to prepare or submit the permitted action.

Expiry, nonces and replay boundaries are part of the authorization

A permission with a spending limit but no expiry remains exposed indefinitely. A permission with an expiry but no unique identifier can be replayed during its valid window. A permission with a nonce but no stateful consumption rule may still be reused if the application cannot mark it as spent.

These fields are mundane, but they turn an intention into a reliable security boundary.

An expiry window makes stale intent fail. A user may authorize an agent to purchase a ticket, settle a position or claim a rebate during a short period. If the agent is offline, compromised or delayed, the authorization expires instead of becoming a lingering asset.

A nonce gives the intent an identity. It should be unpredictable, unique to the user and capability, and bound cryptographically to the action details. The application should reject a second attempt to consume the same nonce.

A replay boundary defines exactly where the authorization is valid. It can include the network, the contract, the user account, the action method, the recipient and the permitted value. A signature or capability that is valid anywhere is not a safely delegated authorization. It is portable power.

For recurring tasks, use a sequence rather than an open ended credential. A user might permit one rebalance per day for seven days, each below a fixed ceiling, with a distinct sequence number. The application tracks the last accepted sequence. An agent that tries to replay day three’s action on day four fails, even if it still possesses the old message.

COMPACT APPLICATIONSCOPED CAPABILITYPROPOSED CALL PLUS PROOFCONSUME N73 AND EXECUTEFAILED VERIFICATIONUSERcreatesIntent 73AI AGENTholds scopedauthorityCOMPACTAPPLICATIONverifiesproposedcallVERIFICATIONGATEStarget,ceiling,expiryLOANPOSITIONrepaymentexecutesREJECTEDinvalidcalls failIntent 73: repay maximum 500; single use; expires 20:00 UTC; nonce N73
Figure 4 - How a single-use delegated repayment is verified and consumed on execution

The protocol should make successful execution consume the authority. This is particularly important where transaction delivery can be retried, copied or observed by an adversary. A failed call may need its own carefully defined behavior. In some designs, a nonce remains usable after a transient failure. In others, an attempted execution burns it to favor safety over availability. That choice should be explicit because it changes how denial of service risk is handled.

Revocation is a control plane, not a promise

Expiry reduces risk eventually. Revocation reduces it now.

If a user suspects that an agent has been compromised, they should not have to wait for every delegated permission to time out. The application should support a revocation path that makes previously issued capabilities fail verification.

There are several ways to express this conceptually. The application can maintain a revocation record keyed to a capability identifier. It can maintain a per user authorization epoch, so increasing the epoch invalidates all earlier delegations. It can keep separate epochs for separate application modules, which prevents revoking a shopping agent from interrupting a health related credential workflow. It can use a root commitment to a set of active permissions, then remove or replace a capability through a user controlled update.

The implementation choice is less important than the security property: an agent should not be able to veto its own revocation, and an application should check revocation during authorization rather than treating it as off chain advice.

Revocation also benefits normal users. A user may change merchants, close a loan, alter risk tolerance or simply stop using an automation service. Ending authority should be as deliberate and accessible as granting it.

A good interface should show active capabilities as a small inventory, not as a hidden security setting. Each entry should identify the agent, the action, the counterparty, the remaining amount, the remaining uses and the expiry. The user should be able to revoke one capability or invalidate an entire agent session.

A threat model for a Compact application

Before writing a delegated flow, application builders should identify who can misbehave and what they can reach.

The agent itself may hallucinate, be prompt injected, run flawed planning logic, suffer a software compromise or be operated by a party whose incentives differ from the user’s. The network may delay or replay messages. A malicious counterparty may try to substitute a destination, solicit extra disclosures or cause an action to fail after extracting useful metadata. The user’s device may be compromised. The application may contain an authorization bug that treats a valid proof as sufficient permission.

The key question is not whether any one component is trusted. It is what each component can do if it becomes untrusted.

For each asset, write down the required protection:

  • Funds: An agent cannot move more than the ceiling or to an unapproved target.
  • Private state: An agent does not receive raw witness data unless it must, and then only for the smallest necessary scope.
  • Identity attributes: A verifier receives only the claim it needs, not a reusable identity profile.
  • Future authority: A stolen capability expires, is single use where possible and can be revoked.
  • Transaction intent: A valid instruction cannot be redirected, modified or replayed.
  • User control: The user can inspect, pause and terminate delegation without relying on the agent.

This exercise reveals a hard truth about agent design. The most damaging attack often does not need to break zero knowledge cryptography. It only needs to persuade or compromise an overprivileged component that the protocol already trusts.

Build a permission envelope, then make the agent fit inside it

A Compact application that uses an agent should define the envelope before choosing the model, hosting provider or automation framework.

Start with the smallest useful action. Avoid “trade for me” when the actual need is “swap up to this amount of Asset X for Asset Y if the quoted rate is at least this threshold.” Avoid “monitor my private credentials” when the need is “submit a proof of age eligibility to this named service before this time.” Avoid “manage collateral” when the need is “repay up to this amount if the health condition crosses this private boundary.”

Then decide where proofs are generated. If the witness is highly sensitive, a user controlled prover environment is preferable to sending the witness to a remote agent. The agent can observe an allowed proof result or receive a commitment to the result, then prepare a constrained call. Where remote assistance is unavoidable, minimize witness exposure and ensure the remote component never receives a credential that also grants broad transfer authority.

Finally, bind authorization to proof without conflating them. The application should require both:

  1. A proof that the private precondition holds.
  2. A capability showing that this agent may invoke this exact action under these exact limits.

Either item alone should fail. A valid proof without authority should not move funds. A valid capability without the required proof should not bypass the private condition.

That is the engineering implication of Syed’s warning. Parameters are not a friendly preference layer placed around an otherwise omnipotent agent. They are the actual security model.

The goal is not an agent that users must trust with everything. It is an agent that can safely be trusted with one bounded thing.

#Midnight#AI agents#privacy#zero knowledge#delegation#capabilities#authorization#Compact#wallet security#revocation#nonces#transaction intents
Jared Zimmerman writes the long technical pieces at Midnight Signal: zero-knowledge proof systems, the Compact toolchain, partner-chain consensus, and what selective disclosure means in practice rather than in a whitepaper. He reads the specifications and the code, and prefers a diagram to an adjective.