8 min read

Can a SOC 2 evidence table prove agent actions?

Build a SOC 2 evidence table that ties agent session approval, per-call review, revocation, and log verification to auditable controls.

Can a SOC 2 evidence table prove agent actions?

Agent activity creates an audit problem that ordinary application logs do not solve. A service account log can tell you that a credential called an endpoint. It usually cannot tell you whether a specific agent process had authority at that moment, whether a human approved the action, whether the authority was later withdrawn, or whether the record you handed to an auditor is the same record produced at the time.

A usable SOC 2 evidence package has to reconstruct a decision, not merely display a timeline. For every meaningful action, an auditor should be able to move from the actor and authorization to the call, the outcome, and the integrity of the retained record. If any join depends on an administrator's memory or a manually edited spreadsheet, the control is weaker than it first appears.

Sallyport is built around that chain: an agent receives action results, while credentials remain in the local encrypted vault and the app records the agent run and each individual call. That design is useful only when you turn its records into testable evidence rather than treating the journal as a compliance prop.

A control needs a reconstructable decision

The AICPA's 2017 Trust Services Criteria are criteria, not a menu of screenshots. The security common criteria ask management to establish and operate controls that restrict logical access, monitor system operation, respond to identified issues, and manage changes. An auditor tests the control you describe, its population, and whether it worked during the examination period.

That distinction matters for agent actions. "The agent needed approval" is a product behavior. "Each newly started agent process required an attributable authorization before it could use a protected action channel, and the company retained records that link authorization to resulting calls" is a control statement that can be tested.

Write the risk before you write the evidence request. A practical risk statement looks like this:

An unapproved or formerly approved agent process could invoke an external API or SSH command using organizational credentials, causing unauthorized access or an unauthorized operational change.

The control should answer the risk in plain language. The evidence should answer five narrower questions:

  1. Which process attempted the action?
  2. What authority did it have at that time?
  3. Who, if anyone, gave that authority?
  4. What exact external action followed?
  5. Can someone detect an attempt to rewrite the history?

Teams commonly mix these questions together. They call a destination allowlist an approval control, call a successful API response an authorization record, or call a log export immutable because the export is read-only. Each claim describes a different thing.

A destination restriction limits where a process can act. Authorization records who allowed a process to act. Call records establish what it attempted and what happened. Integrity verification speaks to whether the retained sequence has been altered. Keep those claims separate in the system description and the evidence table. Auditors do not need fashionable language. They need a control owner who can make a bounded claim and produce the supporting record.

The SOC 2 evidence table auditors can test

Use one evidence table as the working agreement between engineering, security, and the auditor. Do not make it a list of product features. Each row should state the risk, control activity, source population, test method, and failure signal.

Control areaControl activityEvidence populationLikely criteria connectionAuditor testFailure signal
New agent sessionA new agent process must receive session authorization before protected actions runSession journal for the review periodCC6.1, CC6.2Select sessions and trace approval to the first protected callCall exists without a preceding approval or a locked vault denial
Sensitive individual actionA credential marked for approval requires a human decision for each useActivity journal entries for marked credentialsCC6.1, CC7.2Select calls and inspect the decision immediately associated with each callA marked credential was used without an approval record
Session revocationA reviewer can terminate an active session and later calls from it are deniedRevocation events and subsequent attemptsCC6.2, CC7.3Reperform a revocation and test a later attempted actionThe session performs an action after revocation
Call accountabilityEach completed or denied call records the session, destination, operation, result, and timeActivity journalCC7.2Reconcile selected calls to session and result recordsMissing fields, duplicate identifiers, or untraceable calls
Audit integrityA retained encrypted audit sequence can be verified independently without vault accessArchived log ranges and verification recordsCC7.2, CC7.4Run offline verification on a selected retained rangeVerification reports a broken chain or the range is unavailable
System changeCode, configuration, and deployment changes affecting the gateway follow the company's change processPull requests, tickets, test results, deployment recordsCC8.1Trace a sampled production change from approval through deploymentAn unapproved or untested system change reached production

The criterion references are starting points, not a promise of coverage. Your service description, risk assessment, system boundaries, and auditor's judgment determine the final mapping. In particular, do not force every agent record under CC8.1. The AICPA's examples and guidance treat change management as control over changes to application programs and related technology. A call that edits a customer account, sends a support reply, or restarts a remote process is an operational action. It becomes change management evidence only when it is part of an approved and tested change to the system itself.

The table also prevents a common audit-week failure: collecting a perfect artifact from one day. A Type 2 examination asks whether stated controls operated effectively throughout a period. The population column is not paperwork. It tells you what complete universe you must be able to produce before anyone samples it.

Session approval proves process authority, not identity governance

Per session approval is evidence that a particular agent run received permission to use the action gateway. It is not evidence that your company managed employee access correctly, provisioned an identity provider account correctly, or reviewed a cloud administrator role. Those need their own controls and records.

The useful claim is narrower. The first protected call from a new process receives an approval decision before the session can act. The record should preserve a session identifier, process identity, code signing authority where available, decision time, approver identity, and termination state. In Sallyport, the approval card leads with the process's code signing authority, which makes the human decision about the executable that actually requested access rather than a vague label supplied by the agent.

That is a meaningful distinction. An agent can call itself whatever it likes in a prompt, a terminal title, or a process argument. A control that approves a self-reported name invites a simple bypass. A control that presents the code signing authority gives the reviewer a stable attribute to evaluate. It does not eliminate the need to trust that signed software, but it states the trust boundary honestly.

For a session approval test, ask the auditor to select a sample from the session population, then trace each record in both directions:

  • Start with the session approval and find the first protected call that followed it.
  • Start with an activity entry and find the session that authorized it.
  • Confirm the call time falls after approval and before session exit or revocation.
  • Confirm denied sessions have no successful protected calls.
  • Confirm the session record identifies the process strongly enough for your stated control.

Do not rely on a screenshot of an approval dialog. Screenshots are useful for documenting control design, but they are not population evidence. A record must survive after the dialog closes, be queryable by identifier, and join to the activity record without a person deciding which row looks right.

Also avoid claiming that session approval is least privilege when it is not. A session decision can control whether a process may act at all. Least privilege depends on the credentials, destination scope, operations, and permissions available after approval. If one approved agent can use a credential with unrestricted production rights, the approval is a gate, not a scope reduction. Describe it that way.

Per call approval is for actions you cannot safely batch

A per call approval control provides a different assurance than session approval. It asks for a fresh human decision at the moment a particular credential use is about to occur. Use it for actions where the harm lies in the individual invocation, not merely in allowing an agent process to begin work.

Good candidates include a production credential that can change access rights, delete data, alter billing information, publish a deployment, or run commands against an especially sensitive host. The purpose is not to make every agent action tedious. The purpose is to put review at the transaction boundary where a single misuse would matter.

The evidence must bind the approval to one use. A sound activity record has at least:

  • A unique call identifier and associated session identifier.
  • The protected credential reference, without placing its secret value in the record.
  • The channel, destination, operation, and timestamp.
  • The decision state and approver for a call that needed approval.
  • The outcome, including a denied, failed, or completed result.

Do not accept an approval record that appears somewhere near a later action. Time proximity is not binding. If a reviewer approves Call A and the agent performs Call B with the same credential, the evidence must show whether B independently needed and received approval.

This is where teams often overcorrect. They put a human in front of routine read actions, then reviewers approve a stream of nearly identical cards without looking. The control still creates records, but the review has become ceremonial. Keep per call approval for the narrow class of credentials or actions that deserve it. Use session approval for ordinary work, and reduce credential scope separately.

A reviewer needs enough context to make a decision. For an HTTP action, that usually means method, destination, credential identity, and a safe description of the request's effect. For SSH, it means the host identity and command or a constrained command description. Never put the secret itself into the approval payload just to make the evidence richer. A secret disclosed to a reviewer through an approval card is still disclosed.

Revocation must create a denial you can demonstrate

Approve the process, not a label
Approve a new agent process once, with its code-signing authority shown before it can act.

Revocation evidence is worthless if it only records a user interface event. The control is operating when authority ends and a later attempt fails for that reason.

Run this test before an audit asks for it. Start a session that has permission to use a nonproduction test action. Confirm a successful call. Revoke the session while the process remains running. Then make the same process attempt a second call. Preserve the four linked records: the successful first call, the revocation event, the denied second call, and the session state.

Your test worksheet can be as plain as this:

Test ID: AGT-REV-01
Session ID: ____________________
First call ID and result: ____________________
Revocation time and actor: ____________________
Second call ID and denial result: ____________________
Reason shown for denial: ____________________
Reviewer and date: ____________________

The ordering is the control. A revoke event at 14:03 followed by a successful call at 14:07 is either a failure, a clock problem, or evidence that the session identifier does not mean what you said it means. None of those deserve a hand-waved explanation.

Treat ordinary session exit and explicit revocation differently. Exit ends a process because it stopped running. Revocation ends authority because a reviewer chose to withdraw it. Both should block later calls, but only revocation demonstrates that a human can terminate a live run in response to concern. Keep the event types separate in the evidence table.

This control also belongs in incident response practice. If a reviewer sees a suspicious sequence of calls, they should know who can revoke the run, how fast the denial takes effect, and where the event appears in the journal. A written procedure that says disable the agent without naming the actual action is not enough when the agent is already executing work.

Offline verification tests history after the application is out of the room

An activity journal gives you accountability. An independently verifiable hash chain gives you a way to test whether the retained sequence still fits together. These are related but not interchangeable.

Sallyport projects session and activity views from one encrypted, write blind audit log. The offline command sp audit verify checks the chain over ciphertext and does not need vault access. That is useful evidence because the verifier can test retained history without asking the system that produced the report to decrypt credentials or grant access to its vault.

Do not overstate what that proves. Hash chain verification can detect a missing, reordered, or altered record within the verified scope, depending on the chain design and the retained material. It does not prove that the application emitted every event that should have existed. It also does not prove that the time source was accurate, the approver made a sound decision, or the underlying external API did what it claimed. Those are different control questions.

Keep a verification record for a defined retained range. This working-paper format is enough for many teams:

{
  "verification_id": "audit-2026-07-15-01",
  "period_start": "2026-07-01T00:00:00Z",
  "period_end": "2026-07-14T23:59:59Z",
  "command": "sp audit verify",
  "verifier_version": "record the installed version",
  "source_archive": "encrypted audit export identifier",
  "result": "pass or fail",
  "performed_by": "reviewer identity",
  "exceptions": []
}

Do not invent a clean result after a failed verification. Record the failure, preserve the material, determine whether the failure came from export handling, retention, software defect, or suspected alteration, and route it through incident handling. A failed integrity check is not automatically a breach. It is an event that requires investigation because your evidence chain has stopped being trustworthy.

Run verification on a schedule that fits the volume and risk of agent activity, and again before you package evidence. A monthly job may be adequate for a small environment. A team that lets agents operate production systems all day should not wait until quarter end to discover an integrity problem. The schedule is less important than being able to show it ran consistently and that someone handled failures.

Operational actions and system changes need separate proof

Keep credentials out of evidence
Keep API keys and SSH keys in Sallyport's encrypted vault, never in the agent context.

This is the boundary that gets blurred most often. An agent action can change something. That does not make it a controlled system change for CC8.1.

Consider three examples. An agent uses an API to change a customer's subscription status. That is a business operation and needs authorization, traceability, and perhaps review. An agent edits an infrastructure file in a source repository, the pull request receives review, tests pass, and a deployment pipeline applies it. That is a system change. An agent runs an SSH command that edits a production configuration file directly. That is both an operational action with an elevated risk and a probable violation of the change process if your policy requires reviewed deployments.

The evidence package should make these paths visible instead of allowing a reviewer to infer them from prose. Add an action classification to the activity record or the evidence analysis:

Action classPrimary evidenceWhat it does not replace
Read or diagnostic operationSession authorization and call recordReview of access scope and monitoring rules
Business data operationSession or per call approval, call record, outcomeCustomer support process or financial approval where required
Production system operationPer call approval, host or endpoint record, incident or maintenance referenceFormal change control if the operation changes managed configuration
Product or infrastructure changePull request, approval, tests, deployment record, agent activity if usedThe release control itself

CC8.1 expects management to authorize, design, develop or configure, document, test, approve, and implement changes to infrastructure, data, software, and procedures. An agent journal can enrich that story by showing that an agent opened a pull request or invoked a deployment-related action. It cannot substitute for the review, test evidence, and deployment record.

This is unpopular because one audit log feels like it should answer every question. It cannot. Keep the agent activity trail as the record of delegated action. Keep your engineering change records as the proof that system changes followed the required path. Join them only when the agent participated in that path.

Build the evidence package from a population, not a screenshot folder

Put review at the call
Mark a credential for approval on every use when one external action deserves human review.

Build one repeatable package for each review period. The first task is to define the population. For agent activity, that usually means all sessions, all protected calls, all call denials, all revocations, and all log verification runs during the period. If you cannot produce counts or a complete export, you cannot credibly state that an auditor selected from the full population.

Then prepare a small evidence manifest that points to immutable or retained source artifacts. Do not upload a pile of files with names like final-final-audit. Use stable identifiers, source location, period, owner, and a note explaining what the artifact proves.

A reviewer can use this sequence:

  1. Obtain the period's session and activity populations, plus the integrity verification records.
  2. Reconcile the number of session identifiers referenced by activity entries to the session population, then investigate unmatched records.
  3. Select samples across approved sessions, denied attempts, sensitive calls, revocations, and time ranges.
  4. Trace each selected call back to its authorization and forward to its result, then inspect the log verification record that covers its retained range.
  5. For changes to the gateway or related production controls, separately trace the relevant pull request, test, approval, and deployment record.

That sequence exposes gaps quickly. If a call has no session, the authorization join failed. If a session has no process identity, you cannot test the process claim. If a revocation has no later denial test, you only know someone clicked a button. If verification records cover an archive that cannot be reproduced, the integrity claim is thin.

Keep reviewer notes with the sample. A short note such as "Call ID 54b matched Session ID 12a; session approved by employee A; per call approval required and present; activity result completed; audit range verification passed" is more useful than ten screenshots. It tells the next reviewer what was tested and leaves a trail when the control changes.

Evidence fails when owners cannot explain exceptions

The best evidence table still fails if nobody owns the exception path. Agent actions will be denied. Approval requests will expire. Calls will fail at the remote endpoint. Sessions will be revoked. Verification may report a problem. Those outcomes should appear in the population, and a team should know which ones require action.

Define a modest set of exception categories: unauthorized attempt, approval rejection, remote action failure, post revocation attempt, missing record join, and verification failure. Assign an owner, a review cadence, and an expected record for each. Do not force every denied API request into a security incident. Repeated denials from an unexpected signed process probably deserve more attention than an engineer declining their own experimental command.

The useful test is whether someone can explain a selected exception without assembling a story from chat messages. The activity record should state the immediate reason. The session record should identify the run. The follow-up should state whether the team accepted the outcome, corrected configuration, revoked access, or opened incident handling.

This is also where control changes need discipline. If you alter approval behavior, credential flags, logging fields, or the procedure for verifying retained logs, treat that as a change to the control environment. Update the control narrative, test the new behavior, and record the deployment through your existing engineering process. Otherwise your evidence table describes last quarter's system while this quarter's agents use something else.

Do not wait for the auditor to tell you whether the evidence connects. Pick one real session this week, trace it from authorization to call outcome, revoke it in a safe environment, and verify the retained audit range offline. If your team cannot complete that exercise with records already available, fix the evidence path before you argue about control wording.

FAQ

Are activity logs enough evidence for SOC 2?

No. A raw log may show that an API call occurred, but it often cannot show which agent process received authority, who approved it, what credential scope applied, or whether anyone could alter the history later. Build a chain that ties the approval, call, result, revocation state, and integrity check together.

What should session approval evidence include for an audit?

Use session approval to support a control that restricts an agent process before it can act. The evidence needs the process identity, approval decision, approver, time, session identifier, and the session end or revocation event. A card that says approved without those joins is weak evidence.

When should an AI agent require approval for every call?

Per call approval is strongest where the destination action can materially change data, permissions, money movement, production configuration, or source control. Do not require it for every harmless read just to look strict. Put it around the operations whose misuse would create a finding or an incident report.

How do I prove that agent access was revoked?

Revocation evidence should show a specific authority was removed and that a later attempted call failed because of that removal. A screenshot of a revoke button proves almost nothing. Test the denial path and retain both the revoke event and the denied attempt.

What does offline audit log verification prove?

Offline verification checks whether the retained audit history still has the expected cryptographic structure without trusting the running application or its database interface. It does not prove that every business event was captured. You still need controls over what events enter the journal and how teams review exceptions.

Do approved agent actions count as change management evidence?

Not by itself. SOC 2 change management addresses changes to your own system, such as code, infrastructure, configuration, and deployment. An approved agent call to change a customer record is operational activity unless that call is part of a controlled deployment process.

How should we sample agent activity for a SOC 2 audit?

Sample sessions and calls across the review period, then test the population that produced the sample. Include normal approvals, per call approvals, denied calls, revoked sessions, and failed integrity checks if any exist. Auditors will care more about a defensible population and selection method than a decorative spreadsheet.

Is a human click enough to authorize an AI agent?

A human approval can support a control only when the record identifies what was approved and binds that decision to the later action. An approval that says allow agent access without a session, destination, scope, or timing boundary leaves too much room for interpretation.

What fields belong in an AI agent audit trail?

Keep the identity of the human approver, the agent process or service identity, session and call identifiers, timestamps, destination, operation, result, approval state, revocation state, and integrity verification result. Preserve the relation between records, not merely each record in isolation.

How often should we verify a tamper-evident audit log?

An append-only claim is useful only if an independent procedure can detect alteration. Keep the verification command, the verifier version, the exact log range tested, the result, and the person or automated job that ran it. A hash chain that nobody verifies is only a design promise.

Sallyport

Sallyport runs API calls and SSH commands for your AI agent. The keys stay in a local vault on your Mac; you approve each run and every action lands in a sealed journal.

© 2026 Sallyport · Open source under Apache-2.0 · Oleg Sotnikov