Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .github/workflows/trace-adapters-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
- "integrations/otel-genai/**"
- "integrations/langchain/**"
- "integrations/llamaindex/**"
- "integrations/google-adk/**"
- "integrations/openshell/**"
- ".github/workflows/trace-adapters-tests.yml"
push:
Expand All @@ -18,6 +19,7 @@ on:
- "integrations/otel-genai/**"
- "integrations/langchain/**"
- "integrations/llamaindex/**"
- "integrations/google-adk/**"
- "integrations/openshell/**"
- ".github/workflows/trace-adapters-tests.yml"

Expand Down Expand Up @@ -140,3 +142,24 @@ jobs:
run: |
pip install "langchain-core==1.6.0" "langgraph==1.2.11"
python -m pytest integrations/langchain/test_langgraph_interop.py -q

google-adk-adapter:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- name: Test evidence rules without Google ADK
run: |
pip install "agentrust-trace==0.9.0" pytest
python -m pytest integrations/google-adk/test_google_adk_to_trace.py -q
- name: Test released Google ADK interoperability and evidence rules
run: |
pip install "google-adk==2.7.1" "agentrust-trace-tests==0.5.0"
python -m pytest \
integrations/google-adk/test_google_adk_to_trace.py \
integrations/google-adk/test_google_adk_interop.py \
-q
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ TRACE only works as a standard if it is genuinely neutral. Integrations are list
| [Agent Passport System](integrations/aeoess-aps/) | aeoess | trace | community |
| [comply54](integrations/comply54/) | comply54 | trace | community |
| [DecisionAssure](integrations/decisionassure/) | DecisionAssure (a1k7) | trace | community |
| [Google ADK](integrations/google-adk/) | agentrust-io | trace | community |
| [LangChain](integrations/langchain/) | agentrust-io | trace | community |
| [LlamaIndex](integrations/llamaindex/) | agentrust-io | trace | community |
| [Nobulex](integrations/nobulex/) | Nobulex | trace | community |
Expand All @@ -57,6 +58,7 @@ TRACE only works as a standard if it is genuinely neutral. Integrations are list

| Framework | Adapter | Released framework exercised in CI | Evidence boundary |
|---|---|---|---|
| Google ADK | [Google ADK](integrations/google-adk/) | Yes - Google ADK 2.7.1 `InMemoryRunner` plugin lifecycle | Callback-visible invocation, model, and available tool identity; no payloads, retries, agent graph, function-body execution, or policy enforcement |
| LangChain | [LangChain](integrations/langchain/) | Yes — LangChain Core 1.6.0 callback contract | Tool identity and outcome plus model identity; no chain topology or runnable state |
| LangGraph | [LangChain](integrations/langchain/) | Yes — LangGraph 1.2.11 `StateGraph` with a nested tool call | Propagated tool callbacks; no nodes, edges, state transitions, checkpoints, or rollback decisions |
| LlamaIndex | [LlamaIndex](integrations/llamaindex/) | No — current tests use representative event objects | Allow-listed tool and model fields; released-framework interoperability remains unverified |
Expand Down
94 changes: 94 additions & 0 deletions integrations/google-adk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Google ADK to TRACE

Emits a TRACE v0.2 Trust Record from the released Google ADK `BasePlugin`
lifecycle. CI exercises Google ADK 2.7.1 through a real `InMemoryRunner` with a
deterministic local model, so the interoperability test makes no network call.

## Evidence boundary

The plugin runs inside the operator's ADK runner. Its records are first-party
evidence and carry no `origin` block. Without a hardware attestation they use
`runtime.platform: software-only`; building a record does not appraise it, so
`appraisal.status` is `none`.

| Observed from ADK | Supplied by the operator | Not claimed |
|---|---|---|
| Invocation id, model id, available tool name, function-call fingerprint, callback-visible lifecycle outcome | Model provider, workload identity and digest, policy bytes, data class | Prompts, responses, arguments, results, exception text, retries, agent graph, policy enforcement, whether a tool function body ran |

The model provider is operator-supplied because ADK can use models from more
than one provider. A single TRACE record has one model field, so an invocation
that exposes multiple model ids is refused rather than relabelled. A caller may
supply the model id only when ADK exposed none; it may not override an observed
id.

The plugin starts each run as `incomplete`. A successful `after_run` changes it
to `ok`; a reported run error changes it to `error`. A cancelled or interrupted
run that never reaches either callback remains `incomplete`. That is lifecycle
evidence, not a claim that ADK reported a cancellation reason.

Tool starts are retained in call order and correlated with completions through
ADK's function-call id. An unmatched start remains `incomplete`; an unmatched
completion is retained with `observed_start: false`. Neither case is silently
dropped. When an id is absent and more than one same-name start is pending, the
completion is retained as uncorrelated instead of being assigned by FIFO.

These are callback-visible outcomes. Another plugin can short-circuit a tool or
recover its exception. The adapter therefore does not claim that the function
body ran. If an error callback is followed by a recovered completion for the
same fingerprint, both outcomes are retained on one call and the final
callback-visible outcome is `ok`.

## Use it

```bash
pip install agentrust-trace google-adk==2.7.1
```

```python
from agentrust_trace.sign import generate_key, sign_record
from google.adk.apps import App
from google.adk.runners import InMemoryRunner
from google_adk_to_trace import GoogleAdkTracePlugin

plugin = GoogleAdkTracePlugin()
app = App(name="research_app", root_agent=agent, plugins=[plugin])
runner = InMemoryRunner(app=app)
await runner.run_debug("...", quiet=True)

invocation_id = plugin.invocation_ids[-1]
record = plugin.build_record(
invocation_id,
subject="spiffe://example.org/agent/research-bot",
policy_bundle=open("policy.cedar", "rb").read(),
workload_digest="sha256:...",
data_class="internal",
model_provider="google",
)
signed = sign_record(record, generate_key())
plugin.discard(invocation_id)
```

`enforcement_mode` defaults to `declared`: the policy is bound into the signed
record, but Google ADK itself did not evaluate it. Override that value only when
a separate enforcement layer actually evaluated the policy.

One plugin can observe concurrent invocations. It retains state by ADK
invocation id until `discard()` is called, so long-running processes should
discard an invocation after persisting its record.

## Tests

```bash
pip install -r requirements.txt pytest
python -m pytest test_google_adk_to_trace.py -q

pip install google-adk==2.7.1 agentrust-trace-tests==0.5.0
python -m pytest test_google_adk_interop.py -q
```

The first suite exercises evidence construction without installing ADK. The
second uses the released runner and checks success, tool failure, cancellation,
concurrent invocations, payload exclusion, signed TRACE validation, and Level 0
conformance for the optional externally enforced path. The bare ADK path keeps
the honest `declared` policy mode; `agentrust-trace-tests` 0.5.0 predates that
mode, so the conformance fixture uses `advisory` to represent an external layer.
Loading
Loading