End-to-End Agentic AI Observability: Tracing from Agents INTO the Oracle AI Database (using the Java observability provider and server-side OTel exporter)
Build one continuous AI agent observability trace across a Spring Boot workload, Oracle JDBC, and Oracle AI Database server-side execution.
This walkthrough answers a practical AI agent observability question:
can you see one trace that starts with an AI agent request, crosses the
Spring Boot and JDBC layers, and continues inside Oracle AI Database? Yes.
This end-to-end agent context tracing pattern follows the request from the
agent workflow to the SQL and database execution that contributed to its answer.
With Spring Boot, Micrometer, Oracle JDBC observability providers, and
DBMS_OBSERVABILITY, the same request can appear in any
OpenTelemetry-compatible observability backend as application spans, JDBC
spans, and Oracle AI Database server-side spans. This walkthrough uses
Jaeger because it is simple to run and easy to inspect, but the same signal
can be viewed in any OpenTelemetry-compliant observability tool.
That database-internal span is the important part. Typical database observability stops at the database edge: the application trace shows that JDBC waited on the database, then the user must switch tools and manually investigate inside the database. Oracle AI Database keeps the trace continuous. Developers, DevOps teams, and security reviewers can see how long the database actually took, correlate it to database-side evidence, and use the same trace for production monitoring, performance profiling, troubleshooting, security context, and evidence that helps make AI agent answers auditable.
All source code, configuration, scripts, and supporting docs for the demo are available in the observability folder on GitHub.
Key Takeaways
- Oracle AI Database lets the trace continue into database server-side execution instead of stopping at the database edge.
- Spring Boot and Micrometer create the application trace context, while Oracle JDBC adds database client spans.
DBMS_OBSERVABILITYexports Oracle AI Database server-side spans to OpenTelemetry-compatible observability tools; this demo uses Jaeger.- Agent context tracing with
MODULE,ACTION, andCLIENT_IDENTIFIERcreates a foundation for production monitoring and auditable AI agent answers.
What We Are Building
The demo app lives in observability/springboot-oracle-db-otel-demo.
It is a Spring Boot app with two main endpoints:
| Endpoint | Purpose |
|---|---|
GET /trace/roundtrip |
Simple app-to-database trace showing Spring Boot, Micrometer, JDBC, and database server-side spans. |
GET /trace/agent-task/view |
Browser-friendly agentic demo that returns the trace id, agent id, database session metadata, database security context, SQL ID, SQL text, bind values, SQL Monitor preview, DBMS_XPLAN, and an embedded Jaeger trace on one page. Jaeger is the demo viewer; the telemetry is OpenTelemetry-compatible. |
The intended trace shape is:
Browser or curl
-> Spring Boot HTTP span
-> Micrometer observation
-> Oracle JDBC provider spans
-> Oracle AI Database DB Server span
-> HTTPS OTLP endpoint
-> OpenTelemetry-compatible observability backend (Jaeger in this demo)
How Do You Set Up and Run the Example?
The demo can run on any Linux environment or VM with enough memory for Oracle Database Free, Jaeger, an HTTPS proxy, and the Spring Boot app. You can also use an Autonomous Database in Oracle Cloud instead of a local database; the important requirements are JDBC connectivity and a database server-side exporter that can reach an HTTPS OTLP endpoint.
A clean OCI Linux VM verification with Oracle Database Free 23.26.2.0
produced the expected Spring Boot, Oracle JDBC, and oracle-db
server-side spans without setting hidden KSTRC instance parameters. The
normal setup below uses documented DBMS_OBSERVABILITY
configuration, a reachable HTTPS OTLP endpoint, network ACLs, and the
database disttrc trust wallet.
- Install Java 25, Maven, Git, Podman, curl, jq, and OpenSSL.
- Run Oracle Database Free on Linux, or provision an Autonomous Database in Oracle Cloud.
- Clone the source from
github.com/oracle-devrel/oracle-ai-for-sustainable-devand use theobservabilityfolder. - Start Jaeger with OTLP HTTP enabled. In the sample setup, Jaeger receives app and JDBC spans on
http://127.0.0.1:4318/v1/traces. - Put a small HTTPS proxy in front of Jaeger's OTLP endpoint for database server-side export. The sample uses NGINX as
otel-tls-proxy, forwardinghttps://otel-tls-proxy:4318/v1/tracesto Jaeger'shttp://oracle-db-otel-jaeger:4318/v1/traces. - Configure
DBMS_OBSERVABILITY, network ACLs, and the database wallet/trust path so Oracle AI Database can push server-side spans to the HTTPS OTLP endpoint. - Configure, build, and run the Spring Boot app, then open the agent task view or call the JSON endpoint to generate a trace.
sudo dnf install -y podman git java-25-openjdk java-25-openjdk-devel maven jq curl openssl
export JAVA_HOME=/usr/lib/jvm/java-25-openjdk
export PATH="$JAVA_HOME/bin:$PATH"
git clone https://github.com/oracle-devrel/oracle-ai-for-sustainable-dev.git
cd oracle-ai-for-sustainable-dev/observability/springboot-oracle-db-otel-demo
mvn -DskipTests package
Keep database credentials and runtime endpoints outside the repository:
export DB_URL='jdbc:oracle:thin:@//127.0.0.1:1521/FREEPDB1'
export DB_USERNAME='FINANCIAL'
export DB_PASSWORD='<app-user-password>'
export OTLP_TRACES_ENDPOINT='http://127.0.0.1:4318/v1/traces'
export TRACE_SAMPLE_PROBABILITY=1.0
export ORACLE_JDBC_SERVER_TELEMETRY_TRACES_ENABLED=true
export ORACLE_JDBC_SERVER_TELEMETRY_LOGGING_ENABLED=false
export ORACLE_JDBC_TRACEPARENT_CLIENT_INFO_ENABLED=true
export ORACLE_JDBC_TRACELEVEL_CLIENT_INFO_ENABLED=true
java -jar target/springboot-oracle-db-otel-demo-0.0.1-SNAPSHOT.jar
curl -sS http://127.0.0.1:8080/trace/roundtrip | jq .
curl -sS \
'http://127.0.0.1:8080/trace/agent-task?agentId=claims-investigator-agent&task=investigate_payment_anomalies' \
| jq .
For the cohesive browser view, open:
http://127.0.0.1:8080/trace/agent-task/view?agentId=claims-investigator-agent&task=investigate_payment_anomalies
Maven Dependencies and the Oracle JDBC Observability Provider
The app uses Java 25, the Oracle JDBC 23.26 line from Maven Central,
the published Maven Central ojdbc-provider-observability
artifact, and the Oracle JDBC 17 production dependency.
<properties>
<java.version>25</java.version>
<oracle.jdbc.version>23.26.2.0.0</oracle.jdbc.version>
<oracle-database.version>${oracle.jdbc.version}</oracle-database.version>
<ojdbc.provider.observability.version>1.1.0</ojdbc.provider.observability.version>
</properties>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc17-production</artifactId>
<version>${oracle.jdbc.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc-provider-observability</artifactId>
<version>${ojdbc.provider.observability.version}</version>
</dependency>
Spring Boot Actuator creates the observation infrastructure, Micrometer
bridges those observations to OpenTelemetry, and the OTLP exporter sends
spans to the collector. The oracle-database.version property
keeps Oracle JDBC, UCP, wallet/security, and related transitive artifacts
aligned on 23.26.2.0.0.
The Oracle JDBC observability provider implements the JDBC driver
TraceEventListener interface and publishes JDBC events into
OpenTelemetry. Those events include database round trips and connection
behavior, with attributes such as connection id, database operation,
database user, tenant, and SQL ID. SQL text and connection details are
treated as sensitive and are disabled by default unless explicitly enabled.
How Do the Spring Boot and JDBC Spans Get Created?
The Oracle JDBC OpenTelemetry extensions expect the application to already have an active OpenTelemetry context. They do not create the root application trace by themselves. In this demo, Spring Boot Actuator and Micrometer provide the HTTP and application observations, and the Oracle JDBC provider adds child spans for JDBC driver events such as database round trips. The provider also propagates the trace context to Oracle AI Database so the database can export its server-side span into the same trace.
If you do not want to add application instrumentation directly, use the OpenTelemetry Java agent for zero-code Java instrumentation. The Oracle JDBC extensions can then add database round-trip spans as children of the current application span and propagate that context to the server.
Spring Boot sends application and JDBC spans through OTLP HTTP. The demo sends them to Jaeger, but the same OpenTelemetry signal can be collected by any OpenTelemetry-compatible observability platform. Oracle JDBC provider properties enable the JDBC trace listener and identify the Java service in the collector.
spring:
application:
name: springboot-oracle-db-otel-demo
datasource:
url: ${DB_URL}
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
oracleucp:
connection-factory-properties:
"[oracle.jdbc.provider.traceEventListener]": observability-trace-event-listener-provider
"[oracle.jdbc.provider.traceEventListener.unique_identifier]": springboot-oracle-db-otel-demo
management:
otlp:
tracing:
endpoint: ${OTLP_TRACES_ENDPOINT:http://localhost:4318/v1/traces}
tracing:
sampling:
probability: 1.0
How Do We Export Database Server-Side Spans?
The database server-side exporter needs a reachable HTTPS OTLP endpoint.
The verified Linux demo uses Jaeger, which accepts OTLP HTTP on port
4318, and puts a small HTTPS proxy in front of it for database
server-side export. In the sample, that proxy is NGINX with a trusted
local certificate:
Oracle AI Database -> https://otel-tls-proxy:4318/v1/traces
otel-tls-proxy -> http://oracle-db-otel-jaeger:4318/v1/traces
Replace Jaeger with another OpenTelemetry-compatible collector or backend by changing the OTLP endpoint. The important requirement is that Oracle AI Database can reach the endpoint over HTTPS for server-side trace export.
Configure the database with DBMS_OBSERVABILITY, grant network
ACL access to the user executing the SQL session, and place the trusted
wallet where the distributed trace exporter expects it:
WALLET_ROOT/<PDB_GUID>/disttrc.
begin
dbms_observability.add_endpoint(
endpoint_type => dbms_observability.otel_traces,
endpoint => 'https://otel-tls-proxy:4318/v1/traces',
credential_name => null);
dbms_observability.enable_endpoint('https://otel-tls-proxy:4318/v1/traces');
dbms_observability.enable_service_option(dbms_observability.capture_traces);
dbms_observability.enable_service_option(dbms_observability.show_extra_metadata);
dbms_observability.enable_service(dbms_observability.all_services);
end;
/
A clean verification run on Oracle Database Free 23.26.2.0 showed that the
documented DBMS_OBSERVABILITY endpoint setup, the HTTPS OTLP
proxy, the network ACL, and the WALLET_ROOT/<PDB_GUID>/disttrc
trust wallet were sufficient for database server-side spans. Older local
diagnostic runs used hidden KSTRC parameters while debugging export
failures, but those settings are not part of the normal demo setup.
How Does JDBC Propagate the Trace Context?
The app uses the published ojdbc-provider-observability
dependency. It is currently necessary to force a server telemetry state
change before enabling
traces, so the driver piggybacks the telemetry state to the database.
EnumSet<OracleConnection.ServerTelemetry> requestedTelemetry =
EnumSet.of(OracleConnection.ServerTelemetry.Traces);
oracleConnection.setServerTelemetry(
EnumSet.noneOf(OracleConnection.ServerTelemetry.class));
oracleConnection.setServerTelemetry(requestedTelemetry);
How Do We Make the Database Span Useful?
A generic DB Server span proves that the trace crossed into the
database, but the demo makes it more useful by setting database session
fields before the SQL runs. The app uses the Oracle JDBC end-to-end metrics
API for this metadata, so it does not need a separate PL/SQL round trip just
to set MODULE, ACTION, and
CLIENT_IDENTIFIER.
String[] metrics = new String[OracleConnection.END_TO_END_STATE_INDEX_MAX];
metrics[OracleConnection.END_TO_END_MODULE_INDEX] = "agent:claims-investigator-agent";
metrics[OracleConnection.END_TO_END_ACTION_INDEX] = "agent-workload-query";
metrics[OracleConnection.END_TO_END_CLIENTID_INDEX] = "traceId=<trace-id>";
metrics[OracleConnection.END_TO_END_ECID_INDEX] = "<trace-id>";
oracleConnection.setEndToEndMetrics(metrics, (short) 0);
In Jaeger, the orange oracle-db / DB Server span then carries
database-side evidence such as oracle.db.module,
oracle.db.action, oracle.db.session.id,
oracle.db.pdb, and oracle.db.query.sql.id.
Some of these names can also appear in client-side JDBC spans because the
driver can receive database metadata and the application deliberately sets
MODULE, ACTION, and
CLIENT_IDENTIFIER. The important difference is provenance and
timing: the oracle-db / DB Server span is emitted by Oracle AI
Database itself, with database-side duration, response status, session
context, and SQL identity attached to the server's view of the work. A
client span can time the Java round trip, but it cannot by itself prove the
database server's own span timing in the same trace.
How Do We Link the Trace to SQL Diagnostics?
The demo returns a canonical SQL ID from the cursor used for its
DBMS_XPLAN and SQL Monitor lookups. Oracle JDBC spans and
database-exported spans can also expose
oracle.db.query.sql.id, but do not assume that every layer will
report the same cursor. A verified run for the screenshots in this article
returned one canonical SQL ID on the demo page and a different SQL ID on
the selected oracle-db / DB Server span.
Keep the correlation intact with the trace id, database ECID,
MODULE, ACTION, and session id. Then use the
canonical SQL ID returned by the page for its V$SQL, bind
capture, SQL Monitor, and DBMS_XPLAN drill-down. A SQL ID on a
particular span remains useful evidence, but it identifies that span's
database cursor rather than a guaranteed cross-layer identifier.
| Evidence | Where it comes from |
|---|---|
| Visual trace and database server evidence | Trace id, ECID, module, action, session id, and any layer-specific oracle.db.query.sql.id attribute |
| Full SQL text | Canonical SQL_ID -> V$SQL.SQL_FULLTEXT |
| Captured bind samples | SQL_ID -> V$SQL_BIND_CAPTURE |
| Runtime plan | DBMS_XPLAN.DISPLAY_CURSOR, the SQL execution plan with optimizer steps, estimated and actual rows, I/O, memory, and timing |
| SQL Monitor report | DBMS_SQL_MONITOR.REPORT_SQL_MONITOR |
The demo also calls DBMS_SQL_MONITOR.BEGIN_OPERATION around the
agent task. That call is different from setting JDBC end-to-end metrics: it
creates a named database operation for SQL Monitor so the agent task has a
database-side operation id and attributes. The trace and SQL-ID bridge still
work without it, because the workload SQL uses the MONITOR hint
and the app queries V$SQL, V$SQL_BIND_CAPTURE,
SQL Monitor, and DBMS_XPLAN by SQL ID. Keeping
BEGIN_OPERATION makes the demo stronger by giving SQL Monitor a
named server-side operation for the agent task; removing it would simplify
privileges and code, but would lose that named database-operation evidence.
What Does the Agentic AI Demo Page Show?
The browser endpoint keeps the demo cohesive by returning the agent story, database diagnostics, and Jaeger trace on one page:
http://localhost:8080/trace/agent-task/view?agentId=claims-investigator-agent&task=investigate_payment_anomalies
The page includes:
- Agent id and task name.
- Trace id and SQL ID bridge.
- Database session context, including module/action/client identifier.
- Application bind values used by this exact request.
- Full SQL Text heading labeled
from SQL_ID -> V$SQL.SQL_FULLTEXT. - Captured Bind Samples heading labeled
from SQL_ID -> V$SQL_BIND_CAPTURE. - SQL Monitor and
DBMS_XPLANoutput. - An embedded Jaeger trace loaded after a short delay so spans have time to flush.
What Does Success Look Like?
In the verified Linux environment, Jaeger showed a single trace containing both services:
springboot-oracle-db-otel-demo from the Java process and
oracle-db from Oracle AI Database server-side export.
{
"services": [
"oracle-db",
"springboot-oracle-db-otel-demo"
],
"ops": [
"DB Server",
"Execute query",
"Fetch a row",
"http get /trace/agent-task",
"oracle.demo.agent-database-investigation"
]
}
Oracle Database Metrics Exporter (External)
Server-side OpenTelemetry spans answer request-scoped questions: which agent request reached the database, how long that database work took, which SQL ID was involved, and how the database span fits into the same trace as the Java service. For fleet-level and time-series questions, pair that with the external Oracle AI Database Metrics Exporter from oracle/oracle-db-appdev-monitoring.
The exporter is a separate process or container that connects to one or more Oracle AI Database instances and exposes database metrics in standard Prometheus/OpenTelemetry formats. Oracle's exporter project includes default metrics, custom metrics defined in YAML or TOML, support for single instance, clustered, Autonomous, cloud, on-premises, Kubernetes, and container-based databases, plus sample Grafana dashboards.
| Signal | Best question | How it complements this demo |
|---|---|---|
| Server-side OpenTelemetry trace export | What happened during this specific agent request? | Shows the database span in the same trace as Spring Boot, JDBC, SQL ID, module/action, and agent metadata. |
| Oracle AI Database Metrics Exporter | What is happening across the database over time? | Adds dashboards and alerts for resource use, sessions, waits, workload health, and custom business or security metrics. |
A practical setup is to run both signals into the same observability platform. Keep this demo's OTLP trace path for request-level causality, and deploy the exporter beside the database environment for database metrics:
Spring Boot + Oracle JDBC provider -> OTLP traces -> collector/backend
Oracle AI Database server-side exporter -> HTTPS OTLP traces -> collector/backend
Oracle AI Database Metrics Exporter -> Prometheus/OpenTelemetry metrics -> collector/backend
Used together, traces and metrics give a stronger agentic AI operations story: the trace explains one request all the way into Oracle AI Database, while the metrics exporter shows whether that request happened during broader database pressure, session growth, wait spikes, alert-log events, or workload-specific metric changes.
How Does the Trace Connect to Security and Auditing?
The demo correlates its trace with Oracle AI Database Deep Data Security. Observability shows what the agent did; database security explains why Oracle AI Database allowed or denied it. The trace already carries the join keys needed for that correlation:
trace.traceIdidentifies the distributed request.agent.ididentifies the AI actor in the application span.oracle.db.module=agent:<agent-id>identifies the same actor inside Oracle AI Database.oracle.db.actionidentifies the database phase.CLIENT_IDENTIFIER=traceId=<trace-id>gives database security and audit policy a compact correlation value.oracle.db.query.sql.idbridges the trace to SQL text, SQL Monitor,DBMS_XPLAN, and later audit records.
The sample app now includes a Database Security Context
panel backed by a real password-authenticated local Deep Data Security end
user. It works without Entra ID, OCI IAM, OAuth tokens, or a JDBC
EndUserSecurityContext call. The page correlates the trace with
ORA_END_USER_CONTEXT.username, the associated schema,
MODULE, ACTION, CLIENT_IDENTIFIER,
enabled database roles, effective privileges, the granted data role, the
applicable data grant, and V$END_USER_DATA_ROLE for this request.
A row-filtering proof runs in that same traced session and shows both the
number of rows allowed by the data grant and zero visible rows for other
agents.
The panel deliberately separates regular Oracle Database roles from Oracle
AI Database Deep Data Security data roles. A role such as
SELECT_CATALOG_ROLE is a normal session role and appears in
SESSION_ROLES. A DDS data role such as
AGENT_CLAIMS_INVESTIGATOR appears in
DBA_DATA_ROLES and receives data grants in
DBA_DATA_GRANTS. The local setup script
observability/sql/setup_local_deep_data_security.sql creates
the local end user claims-investigator-agent, assigns
AGENT_CLAIMS_INVESTIGATOR with GRANT DATA ROLE, and
grants that role SELECT access to only the agent's event-log rows. The
FINANCIAL database user remains the owning schema rather than
the runtime principal.
A Deep Sec local end user is distinct from a conventional database user.
Data roles cannot be granted directly to the FINANCIAL schema
account. Direct password login as the local end user establishes the
end-user security context in Oracle AI Database and activates the assigned
data role without application-side token propagation. The Entra ID and OCI
IAM provider/API examples remain the right pattern when an application must
propagate externally managed end-user identities through a shared pool user.
A security-aware version can run the same agent workload against protected tables, then show effective database user, enabled roles, policy decisions, rows allowed or filtered, and a denied-operation example. After that, a scoped audit policy can record the same actor, module, action, SQL ID, and trace id so the page shows one story: this agent made this request, Oracle AI Database enforced these policies, and the audit trail recorded it.
The trace itself is not auditing. It is observability: useful for debugging, performance, causality, and visual correlation. Auditing requires durable database records, such as Unified Auditing or Fine-Grained Auditing entries, retained under a security-controlled policy. The best pattern is to use traces to explain the execution path and audit records to prove the security-relevant facts.
A companion design note expands this direction: Agent Security Observability With Oracle AI Database.
How Can Agent Context Tracing Support Model Observability and Auditable AI Agent Answers?
Agent observability should not stop at infrastructure traces. The same task can also be correlated with model-level telemetry: prompt, model, tool calls, retrieval steps, latency, token usage, evaluator scores, and final answer quality. Tools such as LangSmith, OpenTelemetry-based GenAI semantic conventions, or enterprise AI observability platforms can capture those model and agent workflow details.
The useful pattern is to carry the same task or trace identifier through the agent workflow, the Java service, Oracle JDBC, and Oracle AI Database. Then one investigation can answer: which agent ran, which prompt or plan it used, which tool call reached the database, how long the database took, which SQL ran, and which database security policies applied. That ties model observability, application observability, database observability, and security review into one storyline.
References
- Source code for this demo: https://github.com/oracle-devrel/oracle-ai-for-sustainable-dev/tree/main/observability
- Oracle JDBC Observability provider: https://github.com/oracle/ojdbc-extensions/tree/main/ojdbc-provider-observability
- Oracle JDBC OpenTelemetry provider: https://github.com/oracle/ojdbc-extensions/tree/main/ojdbc-provider-opentelemetry
- Oracle
DBMS_OBSERVABILITY: https://docs.oracle.com/en/database/oracle/oracle-database/26/arpls/dbms_observability.html - Oracle SQL monitoring and tracing: https://docs.oracle.com/en/database/oracle/oracle-database/26/tgsql/monitoring-and-tracing-sql.html
- Oracle AI Database application tracing: https://docs.oracle.com/en/database/oracle/oracle-database/26/tgsql/performing-application-tracing.html
- Oracle AI Database Metrics Exporter project: https://github.com/oracle/oracle-db-appdev-monitoring
- Oracle Database Metrics Exporter: https://www.oracle.com/database/database-exporter/
- Day One and Beyond - MultiCloud Observability & Management for Oracle Database@X, Sonali Malik: https://www.youtube.com/watch?v=7vUaDdNzFmQ
- AI Agent Observability: Understand How AI Agents Behave in Gen AI Applications and Ecosystems, Royce Fu and Alex Birzu: https://www.ateam-oracle.com/ai-agent-observability-understand-how-ai-agents-behave-in-gen-ai-applications-and-ecosystems
- OpenTelemetry Java agent: https://opentelemetry.io/docs/zero-code/java/agent/
- OpenTelemetry protocol exporters: https://opentelemetry.io/docs/specs/otel/protocol/exporter/
- Spring Boot tracing: https://docs.spring.io/spring-boot/reference/actuator/tracing.html
FAQ
Does this replace database auditing?
No. The trace is observability, not an audit trail. Use Oracle AI Database Unified Auditing or Fine-Grained Auditing when you need durable security evidence about users, roles, objects, SQL, and policy decisions.
Do I have to use Jaeger?
No. Jaeger is used here because it is easy to run and inspect, but the demo exports OpenTelemetry traces. The same approach can feed any OpenTelemetry-compatible observability tool that can receive the app/JDBC spans and the Oracle AI Database server-side spans.
What makes this different from ordinary database tracing?
Ordinary application traces often stop at the database edge. Oracle AI Database can export database server-side spans into the same trace, so the database portion is visible without breaking continuity or switching immediately to a separate diagnostic workflow.
How does this help make AI agent answers auditable?
It records execution evidence across application and database boundaries. Adding agent id, task, module, action, client identifier, and SQL_ID lets a reviewer correlate an answer with its database work. A complete audit still needs durable prompt, model, tool, identity, and policy records in addition to the observability trace.