# Agent activity export for legal review: build proof

An **agent activity export** must let an outsider answer four plain questions without trusting the person who assembled it: what actions occurred, when they occurred, whether the records changed, and who controlled the material after collection. Most teams can answer the first question. The other three are where a routine incident turns into an argument about evidence.

Do not wait for a subpoena, an employee dispute, a security incident, or a customer complaint to decide what to preserve. By then, retention jobs may have removed logs, people may have opened and rearranged files, and a hurried engineer may have exported only the records that looked relevant. That is understandable. It is also exactly how a review package loses credibility.

This is a practical method for preparing agent action records for counsel, internal investigations, compliance review, or an outside examiner. It does not replace legal advice. It does give legal counsel something far better than a spreadsheet with a reassuring filename.

## Treat the package as evidence, not a report

An evidence package preserves source material and explains its handling. A report selects, interprets, and argues from that material. You may need both, but combining them carelessly creates trouble.

A report can say, "The agent attempted an SSH command against this host at this time." The evidence package should let a reviewer find the underlying action record, see the time representation, inspect the recorded result, confirm which system produced it, and check whether the export has changed. The report belongs beside the package, not inside the only copy of it.

The distinction matters when an early theory proves wrong. Investigators often narrow their focus as they learn more. If they exported a hand-picked set of "bad" events and then discarded the surrounding records, they cannot later test whether a retry, approval, session change, or operator action explains the event. Context is not decoration. It is often the difference between an actual unauthorized action and a misleading sequence of ordinary failures.

Define the collection scope before collecting. Write it in one short statement that names:

- the agent process or session identifiers in scope
- the action channels in scope, such as HTTP and SSH
- the start and end time in UTC
- the systems or accounts covered
- known exclusions and the reason for each exclusion

Do not broaden the scope silently later. Add a supplemental collection instead. For example, if the first package covers a six-hour incident window and a reviewer later requests the preceding day, create a second package with its own manifest and hashes. Link it to the first package in the custody record. That preserves the fact that the first decision had a boundary.

This is also where teams make a damaging mistake: they confuse an activity view with a complete source record. A dashboard can be useful for triage, but it often applies filters, pagination, user preferences, and retention boundaries that are invisible in a screenshot. Collect raw records or the closest available source export, then produce readable views from that material.

## Separate authenticity from completeness

Authenticity and completeness are different claims, and a good package supports each one separately.

Authenticity asks whether a particular record came from the claimed source and whether someone changed it after collection. Hashes, signatures, append-only storage, and hash chains help with this claim. Completeness asks whether the package contains all records that should fall within its stated scope. Queries, source counts, retention settings, and collection notes help with that claim.

Teams often overstate a file hash. A SHA-256 hash can show that `activity.jsonl` now matches the version you hashed earlier. It cannot prove that the file included every action from the period, that the system clock was correct, or that the file originated with the system named in the memo. A hash is excellent evidence of byte-for-byte continuity. It is not a universal truth stamp.

Likewise, an audit chain can expose deletion or alteration within the sequence it covers, but it does not repair a poor scope definition. If you collect only one agent session when the incident involved two, an intact chain for the first session does not make the package complete.

Use a manifest to make these claims inspectable. A manifest should identify the source, scope, collector, collection time, file inventory, and verification material. Keep it in a plain text format that does not require a particular application to read it.

```text
case_reference: IR-2025-017
package_id: 2025-017-agent-actions-01
collected_at_utc: 2025-03-08T14:27:19Z
collected_by: employee-id-1842
source_system: macOS workstation, asset WS-042
scope_start_utc: 2025-03-07T18:00:00Z
scope_end_utc: 2025-03-08T02:00:00Z
channels: HTTP, SSH
included_files:
  - original/activity-records.jsonl
  - original/session-records.jsonl
  - original/audit-verification.txt
  - derived/action-timeline.csv
exclusions: Browser history and local shell history were outside this collection.
```

The `original` directory should contain collected source material. The `derived` directory can contain a CSV timeline, a review memo, or a redacted copy. That separation prevents a common failure: someone opens a JSON file, saves it through an editor that changes line endings or character encoding, and then discovers the original hash no longer matches.

The Federal Rules of Evidence address authenticity in Rule 901 through evidence sufficient to support a finding that an item is what the proponent claims it is. Rule 902(14) specifically addresses certified data copied from an electronic device, storage medium, or file when a qualified person identifies it by a process of digital identification. Those rules do not let technical staff skip documentation. They make the process of identification part of the proof.

## Freeze the source before you make it readable

Collect once, preserve that collection, and do your sorting and formatting on copies. This sounds fussy until the first time an investigator needs to explain why a file changed after the team declared it evidence.

Start by creating a case directory with restrictive access. Record the exact system location from which you collected the records, the account used to collect them, and whether the source remained live after collection. If the source may continue to receive events, write that down. A live system is not a static exhibit, and pretending otherwise produces confused timelines.

Then make a direct source export. Avoid opening files in spreadsheet software before hashing them. Spreadsheet applications routinely reinterpret dates, truncate long values, change delimiters, and treat identifiers as numbers. That may be tolerable in a working analysis file. It is unacceptable for the preserved copy.

On macOS, calculate a SHA-256 inventory from inside the package directory after placing the originals there:

```sh
find original -type f -print0 | sort -z | xargs -0 shasum -a 256 > SHA256SUMS.txt
cat SHA256SUMS.txt
```

The output has one line per file, with a 64-character hexadecimal digest followed by the file path. Save the command output as part of the package and record who ran it. Later, verify against the same inventory with:

```sh
shasum -a 256 -c SHA256SUMS.txt
```

A successful check prints each path followed by `OK`. If a path prints `FAILED`, stop treating the package as unchanged. Preserve the failed copy, document the result, and determine whether a transfer, rename, line-ending conversion, or actual modification caused it. Do not regenerate the hash file and quietly carry on.

File names should be boring and stable. Include the package identifier, source category, and UTC collection time where useful. Avoid names like `final-final-v3` or `suspicious stuff`. A reviewer should not need oral history to distinguish an original export from a filtered analyst worksheet.

NIST Special Publication 800-86, Guide to Integrating Forensic Techniques into Incident Response, emphasizes preserving data and documenting collection and handling. Its advice is older than agent tooling, but the discipline still fits. Agent actions move quickly; that is an argument for better collection notes, not an excuse to lower the standard.

## Record timestamps with their clock context

A timestamp without a defined clock is a partial fact. Preserve the original timestamp value, its time zone or offset, the field name, and any known ordering identifier.

Use UTC as the package's reference time. Express it in ISO 8601 form, such as `2025-03-08T14:27:19Z`. Keep source timestamps exactly as exported too. If a source displays local time, include its configured zone and whether the system synchronized time through an approved service. Do not overwrite a source timestamp merely because the team prefers a different display format.

One agent action can create several times. An action record may include the moment an agent requested an operation, the moment an approval appeared, the time a human approved it, the time the system executed it, and the time a remote service responded. Those are not interchangeable.

For a useful timeline, label them by event rather than collapsing them into a single `timestamp` column. A request at 10:00:01, approval at 10:00:28, execution at 10:00:29, and remote failure at 10:00:31 tells a different story from an execution that occurred before approval. The order can establish or defeat a claim of human control.

Capture sequence identifiers where they exist. A monotonically increasing audit sequence, a session-local call number, or a request identifier can resolve ties when two records share the same timestamp precision. If the records provide only second-level timestamps, say so. Do not manufacture millisecond precision by recording the export time.

Clock disagreement deserves its own note. If the local workstation and a remote API differ by several minutes, preserve that observation and identify the sources. Do not "fix" one record to make the timeline look cleaner. A reviewer may later need to test whether the systems used separate clocks or whether an event crossed a time boundary.

The evidence package should include a short time statement such as: "All timeline displays use UTC. Source values remain in the original files. The workstation reported UTC offset +00:00 during collection. No independent clock comparison was performed." That last sentence may feel unsatisfying, but it is honest. Unsupported certainty causes more damage than a documented limitation.

## Preserve the action and its decision context

An action record needs enough context to distinguish an attempted request, an authorized execution, and a completed external effect. Those are separate events.

For HTTP activity, retain the action time, session or process identifier, method, destination host, path, relevant request headers after secret removal, request body handling, response status, and result metadata. The review package should not contain reusable bearer tokens, passwords, or private keys merely because they passed through an action system. A secret can create a second incident inside the evidence process.

For SSH activity, preserve the target host or host alias, user identity used by the action system, command or command category when logged, authentication result, exit status, and returned output subject to a documented redaction rule. If command output can contain customer data, preserve the original under restricted access and create a review copy that describes each redaction. Black bars without a redaction log make reviewers wonder what else vanished.

The process identity matters as much as the action. Record the agent process that initiated the call, its code-signing authority where available, its session identifier, and the lifetime of the session. A statement that "the coding agent did it" is too vague for legal review. Separate processes can have different origins, different approvals, and different permissions even when a human calls them all the same agent.

Approval records require careful wording. An approval means that a person permitted a defined operation or session under the system's design. It does not prove that the person read every detail, understood every consequence, or had authority under a company policy. Do not make those claims unless separate evidence supports them.

Sallyport records agent runs in a Sessions journal and individual calls in an Activity journal, with both views projected from one encrypted, hash-chained audit log. That design is useful for review because a session-level question and a call-level question can refer back to the same underlying record sequence.

Keep the original request and result relationship intact. A failed call can be just as relevant as a successful one. Repeated failures may show an agent retrying a blocked credential, a changed endpoint, or an operator correcting a configuration. Removing failures to make a timeline shorter often removes the explanation for the one success that matters.

## Verify tamper evidence while the source remains available

Run integrity verification during collection and save the output with the original records. A later verification still has value, but an early result ties the package to the state of the logging system at collection time.

A hash-chained log works by linking each record to prior material through cryptographic data. Altering, deleting, or inserting records ordinarily breaks the later link relationship. This gives reviewers a specific property to test: whether the sequence verifies as issued. It does not prove the logged action was ethically justified or that every possible system event reached the log. Keep those claims separate.

For a Sallyport audit log, run `sp audit verify` against the collected source before relying on the journal views. The verification can run offline over ciphertext and does not require a vault key, which lets an investigator preserve an integrity result without obtaining the credentials used for external actions.

Save the full terminal transcript, including the command, current directory, account identity if your procedure captures it, start and finish times, and exit status. A screenshot is weaker than text because it is difficult to search, copy, and independently rerun. If the command reports a failure, retain that result. Do not export only the records that appear to verify.

Verification needs repeatable conditions. Note the application version, operating system version where relevant, and the exact collection path. If the verification tool depends on a particular local installation, preserve a record of that dependency. You do not need to package every executable by default, but reviewers should know what they would need to reproduce the check.

A simple verification note can read: "Collector ran the audit verification command at 2025-03-08T14:31:02Z against the copied encrypted audit log in `original/`. The command exited successfully. The unedited terminal transcript is `original/audit-verification.txt`." If it did not exit successfully, say that plainly and record the effect on the package. Integrity evidence is useful because it can contradict your preferred explanation.

## Keep a custody record that names people and transfers

Chain of custody is a chronological record of possession and control. It is not a signature page completed after the fact when someone asks for one.

Start the record when the collector creates the package. Each entry should state the package identifier, date and time in UTC, person or service account transferring control, recipient, purpose, transfer method, storage location, and the package hash or hash inventory reference. If one person keeps custody throughout collection, record that too.

Use names or stable internal identities that a company can resolve later. "Security team" is not a custodian. "Jane from legal" is not enough either. People change roles, leave companies, and remember events differently under pressure.

```text
2025-03-08T14:38:11Z
Package: 2025-017-agent-actions-01
Released by: employee-id-1842
Received by: legal-ops-id-77
Purpose: counsel review under incident hold
Method: encrypted internal file transfer
Integrity reference: SHA256SUMS.txt verified before transfer
Storage: matter workspace, restricted folder
```

When a transfer uses encrypted storage or a secure file exchange, record the method but do not assume encryption proves custody. Encryption protects confidentiality in transit. The custody entry establishes who intentionally transferred and received the package. Ask the recipient to acknowledge receipt, then record any later copy made for a consultant, insurer, regulator, or outside counsel.

Access logs can support the custody record, but they do not replace it. A storage log may show that an account accessed a file. It cannot always explain why that account accessed it, whether the account belonged to the expected person at the time, or whether an approved transfer occurred outside the storage system.

Avoid sending the only original by ordinary email. Email creates uncontrolled copies, auto-forwarding risk, retention complications, and ambiguity about attachment versions. If counsel needs a copy, create a documented distribution copy, verify its hash after transfer, and preserve the original in the controlled location.

## Redaction should be reversible in process, not in files

Redact for a stated audience and purpose, but preserve an unredacted original when law, policy, and the investigation require it. Do not make the redacted version the only surviving package.

Agent records can contain secrets, source code, personal data, customer data, internal hostnames, or operational details that create fresh risk if broadly shared. Legal review rarely requires a reusable API credential or private SSH material. Exclude those from the review copy and explain how the collection process handled them. If a source export contains secrets, restrict the original more tightly instead of distributing it to every reviewer.

Use a redaction log with a row for each redacted item or consistent category. State the file, record identifier, field, reason, person who performed the redaction, date, and whether the original remains available under restricted access. A reviewer should be able to tell the difference between a redacted authorization header and a removed action result.

Do not rely on visual overlays in PDFs or screenshots. Improper redaction has exposed underlying text often enough that it should never be treated as a minor production detail. Create a new review artifact from a controlled copy, inspect it with ordinary extraction tools, and verify that the sensitive content no longer appears. Then hash the redacted artifact separately. Its hash must not replace the original inventory.

A filtered timeline can be helpful, especially when a case spans thousands of routine calls. Label it as a derived exhibit and include the filter logic. For example: "Includes calls to the named customer tenant between the stated UTC times; excludes all other destinations; source records remain in original/activity-records.jsonl." That sentence gives counsel a way to explain what the exhibit is without claiming it is the complete audit history.

## Make the package reviewable six months later

The person who collects the package may not be the person who explains it later. Write collection notes for the person who inherits the matter after the incident chat has disappeared and the original engineer has forgotten the details.

Include a short readme that answers practical questions: which files are originals, which are derived, what tool produced each export, how to verify hashes, how to interpret timestamps, and where access to the preserved original is controlled. Keep opinions in a separate incident analysis unless the package labels them clearly as an analyst statement.

Sallyport's vault gate, session authorization, and per-call approvals can create records that help explain human control around an action. Preserve the exact level of approval evidence that the matter needs, then avoid claiming that a product control answers a legal question that belongs to policy, authority, or intent.

Run one dry exercise before an investigation forces the issue. Have a colleague who did not collect the package use only the readme, manifest, hashes, and verification transcript to answer: Which source records are included? Can I verify them? What time basis applies? Who had custody? If that colleague has to ask the collector basic questions, the package is not ready.

The first useful improvement is usually unglamorous: create a case directory template, a plain-text manifest, a hash inventory command, and a custody log now. When a real incident arrives, those four items keep a hurried export from becoming an unverifiable story.
