Skip to main content

Vendor-neutral evidence and detection plane for tool-using agents

Project description

ActionLineage

Know what the agent did, and show what changed.

ActionLineage is an alpha-stage, vendor-neutral evidence and detection plane for tool-using agents. It correlates agent intent, delegated identity, tool execution, and independently observed side effects into investigation-ready local evidence.

The central rule is simple: a successful tool response is an acknowledgement, not proof of a side effect. ActionLineage records requested, authorized, dispatched, acknowledged, observed, verified, unverified, timed-out, conflicting, and not-dispatched outcomes as separate facts.

Current Maturity

This repository is a public alpha. Core evidence recording is usable for local evaluation and fixture-backed integration work, but service deployments, external adapters, cloud observers, containers, package-index publication, and attested release artifacts are preview or external-validation surfaces until they are externally validated.

Surface Maturity Evidence
Event envelope, redaction, local journal, SQLite projection Alpha-supported Unit, compatibility, projection, and security tests
Deterministic verified/unverified/conflicting/not-dispatched demo Alpha-supported make demo, demo tests, contract validation
Case export, graph export, grounded summary, static console Alpha-supported Projection and console tests
Lineage Contracts, sequence detections, Lineage Lab Local-proof Contract, detection, and replay tests
MCP, policy, OpenTelemetry, service, Postgres, cloud/Kubernetes fixtures Preview Optional extras and local fixture tests
Package-index publication, attested artifacts, external audits, production history Planned or external-validation-required See docs/DECISIONS_REQUIRED.md

Full claim mapping lives in docs/QUALITY_SCORECARD.md.

Five-Minute Local Evaluation

Prerequisites:

  • Python 3.13 or newer
  • uv
  • make for convenience targets

Install all optional extras used by the test suite:

uv sync --locked --all-extras

Run the deterministic local demo:

make demo

The demo requires no model API key, cloud account, external service, or internet access. It writes artifacts under build/actionlineage-demo/:

  • evidence.jsonl: canonical append-only local journal.
  • projection.sqlite: rebuildable query projection.
  • timeline.json: compact event-order summary.
  • incident.json: machine-readable incident export.

Inspect the evidence:

uv run actionlineage journal verify build/actionlineage-demo/evidence.jsonl

uv run actionlineage projection timeline \
  build/actionlineage-demo/projection.sqlite \
  --trace-id trace_demo_evidence_plane

uv run actionlineage projection summarize \
  build/actionlineage-demo/projection.sqlite \
  --trace-id trace_demo_evidence_plane

uv run actionlineage projection export-case \
  build/actionlineage-demo/projection.sqlite \
  build/actionlineage-demo/case \
  --trace-id trace_demo_evidence_plane

uv run actionlineage projection export-console \
  build/actionlineage-demo/projection.sqlite \
  build/actionlineage-demo/console.html \
  --trace-id trace_demo_evidence_plane

uv run actionlineage contract validate \
  contracts/examples/outbound-http.json \
  build/actionlineage-demo/evidence.jsonl

Open build/actionlineage-demo/console.html in a browser to review the static timeline, event details, graph, verification matrix, and case context.

The stricter contracts/examples/restricted-exfiltration.json contract is a design example for detection coverage; it is not the five-minute demo contract.

What The Demo Shows

The default scenario emits a deterministic local journal that includes:

  • a recorded human intent and agent run;
  • a verified file-read side effect corroborated by a local filesystem observer;
  • an acknowledged HTTP send that remains unverified because acknowledgement is not side-effect evidence;
  • a conflicting receiver observation represented as side_effect.conflict_detected;
  • a policy-denied shell-like request represented as tool.execution.not_dispatched with downstream_forwarded=false.

Evidence Lifecycle

State Meaning
agent.intent.recorded A human, service, scheduler, or agent initiated a run.
tool.execution.requested An agent or adapter requested a tool invocation.
tool.execution.authorized An optional policy or approval path allowed the request.
tool.execution.dispatched The request crossed the tool boundary.
tool.execution.acknowledged The tool or adapter returned a response.
side_effect.observed A named observer recorded resource or environment evidence.
side_effect.verified Corroborating evidence supports the subject event.
side_effect.unverified Evidence is insufficient or only self-reported.
side_effect.timed_out Observation or verification did not complete in time.
side_effect.conflict_detected Evidence sources disagree and both sides are retained.
tool.execution.not_dispatched A request was blocked, denied, or not sent downstream.

Verification requires independent or explicitly identified corroborating evidence. Missing observations are reported as missing observations only.

Architecture

flowchart LR
    Client["Agent / client"] --> Adapter["Optional adapter"]
    Adapter --> Journal["Append-only local journal"]
    Adapter --> Tool["Tool runtime"]
    Tool --> Adapter
    Observer["Observer adapters"] --> Journal
    Verifier["Verification helpers"] --> Journal
    Journal --> Projection["Rebuildable projection"]
    Projection --> Timeline["Timeline, export, console"]
    Journal --> Contracts["Lineage Contracts"]
    Journal --> Lab["Lineage Lab"]
    Journal --> Exporters["Optional exporters"]

Core packages do not import MCP, OpenTelemetry, model-provider SDKs, FastAPI, or cloud SDKs. Those surfaces live behind optional adapter or service boundaries.

How This Differs

Tooling category Main focus ActionLineage difference
Distributed tracing Request flow and latency Adds evidence status, side-effect verification, and investigation exports
Agent gateway Mediation or policy enforcement Treats enforcement as optional adapter behavior
Guardrail Preventing or blocking actions Preserves evidence, uncertainty, and conflicts even when no block occurs
SIEM/logging Event collection and search Adds causal evidence links and telemetry contract validation

Python API Example

from datetime import UTC, datetime
from pathlib import Path

from actionlineage import (
    Classification,
    Correlation,
    EvidenceNormalizer,
    EvidenceRecord,
    EvidenceSourceKind,
    EventType,
    FixedClock,
    FixedIdGenerator,
    LocalJournal,
    NormalizedAction,
    NormalizedResource,
    Principal,
    PrincipalType,
    ResourceType,
    Sensitivity,
    Source,
    ToolIdentity,
    import_evidence_batch,
    verify_journal,
)

journal_path = Path("build/example/evidence.jsonl")
journal = LocalJournal(journal_path)
normalizer = EvidenceNormalizer(
    correlation=Correlation(trace_id="trace_example", run_id="run_example"),
    source=Source(component="example_adapter", instance_id="local", version="0.1.0a2"),
    principal=Principal(principal_id="agent_example", principal_type=PrincipalType.AGENT),
    classification=Classification(sensitivity=Sensitivity.INTERNAL),
    clock=FixedClock(datetime(2026, 1, 1, tzinfo=UTC)),
    id_generator=FixedIdGenerator(("evt_example_001", "evt_example_002")),
)

intent = EvidenceRecord(
    idempotency_key="example-intent-001",
    source_kind=EvidenceSourceKind.LOCAL_FUNCTION,
    event_type=EventType.AGENT_INTENT_RECORDED,
    payload={"intent": {"summary": "Read a workspace report"}},
    sort_key="000",
)

action = EvidenceRecord.from_action(
    idempotency_key="example-action-001",
    source_kind=EvidenceSourceKind.LOCAL_FUNCTION,
    sort_key="001",
    action=NormalizedAction(
        action_type="read",
        tool_identity=ToolIdentity(
            name="safe_file_read",
            descriptor_hash="sha256:example_descriptor",
            adapter="local",
        ),
        resources=(
            NormalizedResource(
                resource_type=ResourceType.FILE,
                identifier="demo://workspace/report.txt",
            ),
        ),
    ),
)

result = import_evidence_batch([intent, action], normalizer=normalizer, journal=journal)
assert result.ok
assert verify_journal(journal_path).ok

See docs/API_REFERENCE.md for alpha-supported public imports and preview API boundaries.

CLI Highlights

uv run actionlineage version
uv run actionlineage demo run --output-dir build/actionlineage-demo
uv run actionlineage journal verify build/actionlineage-demo/evidence.jsonl
uv run actionlineage projection timeline build/actionlineage-demo/projection.sqlite --trace-id trace_demo_evidence_plane
uv run actionlineage projection explain-event build/actionlineage-demo/projection.sqlite evt_demo_11
uv run actionlineage projection export-incident build/actionlineage-demo/projection.sqlite --trace-id trace_demo_evidence_plane
uv run actionlineage projection export-graph build/actionlineage-demo/projection.sqlite --trace-id trace_demo_evidence_plane
uv run actionlineage projection export-desktop-bundle build/actionlineage-demo/projection.sqlite build/actionlineage-demo/desktop --trace-id trace_demo_evidence_plane
uv run actionlineage contract validate contracts/examples/outbound-http.json build/actionlineage-demo/evidence.jsonl

See docs/CLI_REFERENCE.md for the full command reference.

Documentation Map

Packages and Extras

The repository currently ships as one Python distribution with optional extras:

uv sync --locked                 # core
uv sync --locked --extra adapters
uv sync --locked --extra service
uv sync --locked --all-extras

Core dependencies are intentionally small: Pydantic and Typer. Optional extras hold MCP, OpenTelemetry, SQLAlchemy, FastAPI, JWT, and related integration dependencies.

Security Model In One Paragraph

ActionLineage is not a sandbox, model guardrail, DLP engine, or universal proof system. It records redacted, structured, causally linked evidence and verifies local journal consistency under documented trust assumptions. When a report says an outcome is verified, it means the named evidence source corroborated it within the stated limitations. When no observation exists, the system reports that no observation was recorded.

Development

uv sync --locked --all-extras
uv run ruff check .
uv run ruff format --check .
uv run mypy src
uv run pytest
uv run python scripts/check_claims_language.py .
uv run python scripts/secret_scan.py .
uv run pip-audit

Before release, also run:

uv run python scripts/generate_sbom.py --output build/actionlineage-sbom.json
uv run python scripts/generate_release_provenance.py \
  --dist-dir dist \
  --output build/actionlineage-release-provenance.json
uv build

License

Apache License 2.0. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

actionlineage-0.1.0a2.tar.gz (303.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

actionlineage-0.1.0a2-py3-none-any.whl (134.1 kB view details)

Uploaded Python 3

File details

Details for the file actionlineage-0.1.0a2.tar.gz.

File metadata

  • Download URL: actionlineage-0.1.0a2.tar.gz
  • Upload date:
  • Size: 303.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for actionlineage-0.1.0a2.tar.gz
Algorithm Hash digest
SHA256 3ab6056d08d458e983c691946507e904532c312df907f79d1cb744d1885b87d1
MD5 c3bc7f21c6725dec4f4b7f75fae92086
BLAKE2b-256 2c2eb7893f8e910a6b320e2eb66e97fac46dc96d6ba334f54fd5577e6f6f0eae

See more details on using hashes here.

Provenance

The following attestation bundles were made for actionlineage-0.1.0a2.tar.gz:

Publisher: release.yml on VectorTrace-Labs/ActionLineage

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file actionlineage-0.1.0a2-py3-none-any.whl.

File metadata

  • Download URL: actionlineage-0.1.0a2-py3-none-any.whl
  • Upload date:
  • Size: 134.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for actionlineage-0.1.0a2-py3-none-any.whl
Algorithm Hash digest
SHA256 45b2e81267b92ea69687ab9a0dfb1b2e32ffca4e1263eeea53d84ae00f0ab0d0
MD5 6b7e8bc29667d894c63e1e077d1905f9
BLAKE2b-256 de8571b6705cdf953360ca793c69d9bb8492ea3d8b99da1b1ed0cdbf0f8e7836

See more details on using hashes here.

Provenance

The following attestation bundles were made for actionlineage-0.1.0a2-py3-none-any.whl:

Publisher: release.yml on VectorTrace-Labs/ActionLineage

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page