For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.
Audit logs
Access audit logs in Solo Enterprise for agentregistry to track who performed a specific action on a registry resource.
Solo Enterprise for agentregistry captures a structured audit trail of registry and governance activity. Audit events record who performed an action, the resource that was affected, whether the action succeeded, and the timestamp the action was executed. Registry admins can use the audit log to investigate incidents, verify compliance, and understand access patterns across the registry.
Audit events are organized into four activity types, each emitted to a dedicated OTel logger scope so you can route and retain them independently. For an example configuration, see Route scopes to different backends.
| Activity type | OTel scope | What is captured |
|---|---|---|
lifecycle | audit.resource_activity | Creation, update, and deletion of registry resources, such as agents, MCP servers, skills, prompts, access policies, gateways, and secrets. |
approval | audit.resource_activity | Approval requests that are submitted, approved, revoked, and withdrawn. |
applied_resource | audit.resource_activity | AI artifacts that are deployed to a connected runtime, such as AWS Bedrock AgentCore or Solo Enterprise for kagent. |
authorization | audit.authz | All approved, denied, and failed permission checks. |
For details about the fields that are included in an event stream, see Event schema.
Enable audit logging
Audit logging is disabled by default. To enable audit logging, you can either update your Helm installation with the audit.* fields or set the corresponding environment variables.
When you enable audit logging, you have the option to also deploy a dedicated OTel collector with the audit.collector.enabled Helm value. The collector is configured to buffer event streams in write-ahead logs (WAL) and to forward events to your own OTLP-compatible audit platform that you define with the audit.destination.otlp.endpoint Helm value. For example, you can use a SIEM platform, such as Splunk or Microsoft Sentinel, or a log aggregator, such as Loki or OpenSearch. If the audit platform becomes unavailable, events accumulate on disk and are replayed with retry and backoff settings after the platform becomes available again. Using the built-in relay collector is optional. You can also choose to forward event streams from the registry server to your audit platform directly. In this case, set audit.collector.enabled=false.
The following table shows the Helm values and corresponding environment variables that you can use to enable audit logging in Solo Enterprise for agentregistry.
| Helm value | Environment variable | Description | Default |
|---|---|---|---|
audit.enabled | AUDIT_ENABLED | Enables audit logging. When enabled, you must set the endpoint for your OTLP-compatible audit platform in audit.destination.otlp.endpoint. | false |
audit.destination.otlp.endpoint | AUDIT_OTLP_ENDPOINT | OTLP/gRPC endpoint that receives audit events, for example audit-collector.namespace.svc.cluster.local:4317. Required when audit.enabled=true. | — |
audit.destination.otlp.insecure | AUDIT_OTLP_INSECURE | Disables transport security on the OTLP connection. Set to true for in-cluster plaintext. | false |
audit.collector.enabled | — | Deploys the bundled OTel collector relay alongside the registry server. Can only be set if audit.enabled=true. | false |
audit.authz.allowedDecisions | AUDIT_AUTHZ_ALLOWED_DECISIONS | Controls which successful authorization decisions are emitted on the audit.authz OTel scope. Denials and errors are always emitted. The following values are supported.
| sensitive |
Local testing
For local testing, deploy a lightweight debug collector that receives audit events from the registry server directly and prints them to stdout. This way, you can inspect events with the kubectl logs command without the requirement of using a SIEM or other audit platform.
Note
If you have an existing audit platform that you want to use, see the Production: Bundled OTel collector relay guide instead.
Deploy a debug OTel collector. The collector listens for OTLP/gRPC events from the registry server on port 4317 and prints each event in full detail to
stdout. It has no persistent storage and is intended for development and testing only.kubectl apply -f- <<EOF apiVersion: v1 kind: ConfigMap metadata: name: audit-debug-collector namespace: agentregistry-system data: config.yaml: | receivers: otlp: protocols: grpc: endpoint: "0.0.0.0:4317" exporters: debug: verbosity: detailed service: pipelines: logs: receivers: [otlp] exporters: [debug] --- apiVersion: apps/v1 kind: Deployment metadata: name: audit-debug-collector namespace: agentregistry-system spec: replicas: 1 selector: matchLabels: app: audit-debug-collector template: metadata: labels: app: audit-debug-collector spec: containers: - name: collector image: otel/opentelemetry-collector-contrib:0.148.0 args: ["--config=/conf/config.yaml"] volumeMounts: - name: config mountPath: /conf volumes: - name: config configMap: name: audit-debug-collector --- apiVersion: v1 kind: Service metadata: name: audit-debug-collector namespace: agentregistry-system spec: selector: app: audit-debug-collector ports: - name: otlp-grpc port: 4317 EOFVerify that the collector is deployed successfully.
kubectl get pods -n agentregistry-system | grep debugExample output:
audit-debug-collector-77c4bf9964-mt6h2 1/1 Running 0 71sSave your current Helm values to a file.
helm get values agentregistry --namespace agentregistry-system -o yaml > agentregistry-values.yaml open agentregistry-values.yamlAdd the following values to your Helm values file to enable audit logging. The registry server emits audit events and sends them to your debug collector directly. Note that the bundled relay collector is not enabled. If you want to enable the relay collector, refer to the Production: Bundled OTel collector relay guide.
audit: enabled: true # Instructs the registry server to emit audit events destination: otlp: endpoint: "audit-debug-collector.agentregistry-system.svc.cluster.local:4317" # Debug collector endpoint insecure: trueUpdate your Helm installation.
helm upgrade agentregistry \ oci://us-docker.pkg.dev/solo-public/agentregistry-enterprise/helm/agentregistry-enterprise \ --namespace agentregistry-system \ --version 2026.8.0 \ -f agentregistry-values.yamlCreate an AccessPolicy resource to trigger a
lifecycleaudit event.arctl apply -f- <<EOF apiVersion: ar.dev/v1alpha1 kind: AccessPolicy metadata: name: audit-test spec: principals: - kind: Role name: registry-viewer rules: - actions: - "registry:read" resources: - kind: agent name: "*" EOFReview the logs of the debug collector and verify that you see the audit event. To learn more about every field that is included in the audit log, see Event schema.
kubectl logs -n agentregistry-system deploy/audit-debug-collector -f --since=1mExample output:
2026-07-07T07:19:18.921Z info Logs {"resource": {"service.instance.id": "778040e4-db9c-42b6-a839-47fbec21055e", "service.name": "otelcol-contrib", "service.version": "0.148.0"}, "otelcol.component.id": "debug", "otelcol.component.kind": "exporter", "otelcol.signal": "logs", "resource logs": 1, "log records": 1} 2026-07-07T07:19:18.922Z info ResourceLog #0 Resource SchemaURL: Resource attributes: -> service.name: Str(agentregistry) -> service.namespace: Str(agentregistry-system) ScopeLogs #0 ScopeLogs SchemaURL: InstrumentationScope audit.resource_activity LogRecord #0 ObservedTimestamp: 2026-07-06 21:31:49.631142674 +0000 UTC Timestamp: 2026-07-06 21:31:49.631130633 +0000 UTC SeverityText: SeverityNumber: Info(9) EventName: agentregistry.audit.lifecycle Body: Empty() Attributes: -> event.name: Str(agentregistry.audit.lifecycle) -> event.schema_version: Str(v1) -> event.activity: Str(lifecycle) -> event.action: Str(create) -> actor.subject: Str(b0875cff-fa22-4fac-b3a9-90c81c6ae83c) -> actor.type: Str(user) -> log.record.uid: Str(0dc4b541-b246-44d3-a684-3db49a4ab78d) -> actor.roles: Slice(["admins"]) -> actor.email: Str(admin-user@example.com) -> actor.name: Str(Admin User) -> resource.kind: Str(AccessPolicy) -> resource.namespace: Str(default) -> resource.name: Str(audit-test) Trace ID: Span ID: Flags: 0 {"resource": {"service.instance.id": "778040e4-db9c-42b6-a839-47fbec21055e", "service.name": "otelcol-contrib", "service.version": "0.148.0"}, "otelcol.component.id": "debug", "otelcol.component.kind": "exporter", "otelcol.signal": "logs"}Optional: Remove the AccessPolicy.
arctl delete accesspolicy audit-test
Production: Bundled OTel collector relay
For production, Solo Enterprise for agentregistry can deploy a dedicated in-cluster OTel collector relay that sits between the registry server and your SIEM platform. The relay collector is configured to buffer event streams in write-ahead logs (WAL) and to forward events to your own OTLP-compatible audit platform that you define with the audit.destination.otlp.endpoint Helm value. For example, you can use a SIEM platform, such as Splunk or Microsoft Sentinel, or a log aggregator, such as Loki or OpenSearch. If the audit platform becomes unavailable, events accumulate on disk and are replayed with retry and backoff settings after the platform becomes available again.
Get the endpoint of your audit platform. The endpoint must be accessible from the cluster’s pod network.
Save your current Helm values to a file.
helm get values agentregistry --namespace agentregistry-system -o yaml > agentregistry-values.yaml open agentregistry-values.yamlAdd the following values to your Helm values file. Make sure to set the endpoint of your audit platform that you retrieved earlier in the
audit.destination.otlp.endpointfield. You also enable the bundled relay collector that receives event streams from the registry server and forwards them to the endpoint of your audit platform.audit: enabled: true # Instructs the registry server to emit audit events collector: enabled: true # Deploys the bundled relay collector destination: otlp: endpoint: "<your-siem-or-audit-backend>.<namespace>.svc.cluster.local:4317" # Endpoint to your audit platform insecure: trueUpdate your Helm installation to apply the changes.
helm upgrade agentregistry \ oci://us-docker.pkg.dev/solo-public/agentregistry-enterprise/helm/agentregistry-enterprise \ --namespace agentregistry-system \ --version 2026.8.0 \ -f agentregistry-values.yamlCreate an AccessPolicy resource to trigger a
lifecycleaudit event.arctl apply -f- <<EOF apiVersion: ar.dev/v1alpha1 kind: AccessPolicy metadata: name: audit-test spec: principals: - kind: Role name: registry-viewer rules: - actions: - "registry:read" resources: - kind: agent name: "*" EOFReview the events in your audit platform and verify that you see a lifecycle event that looks similar to the following. To learn more about every field that is included in the audit log, see Event schema.
{ "severityNumber": 9, "severityText": "", "body": "", "scope": "audit.resource_activity", "attributes": { "log.record.uid": "01960f2a-8b3c-7d4e-9a1b-2c3d4e5f6a7b", "event.name": "agentregistry.audit.lifecycle", "event.schema_version": "v1", "event.activity": "lifecycle", "event.action": "create", "actor.subject": "b0875cff-fa22-4fac-b3a9-90c81c6ae83c", "actor.type": "user", "actor.email": "admin-user@example.com", "actor.name": "Admin User", "actor.roles": ["admins"], "resource.kind": "AccessPolicy", "resource.namespace": "default", "resource.name": "audit-test" } }Optional: Remove the AccessPolicy.
arctl delete accesspolicy audit-test
Event schema
Audit events are emitted as structured OpenTelemetry (OTel) log records over OTLP, and are organized into four activity types across two OTel logger scopes. The scopes are separated at the OTel level so you can route them through different collector pipelines that are configured to your needs. For example, you can apply different retention periods or forward the data to different audit backends.
The following example shows a lifecycle event emitted when an agent is created.
{
"severityNumber": 9,
"severityText": "",
"body": "",
"scope": "audit.resource_activity",
"attributes": {
"log.record.uid": "01960f2a-8b3c-7d4e-9a1b-2c3d4e5f6a7b",
"event.name": "agentregistry.audit.lifecycle",
"event.schema_version": "v1",
"event.activity": "lifecycle",
"event.action": "create",
"actor.subject": "b0875cff-fa22-4fac-b3a9-90c81c6ae83c",
"actor.type": "user",
"actor.email": "user@example.com",
"actor.name": "Example User",
"actor.roles": ["registry-viewer"],
"resource.kind": "Agent",
"resource.namespace": "default",
"resource.name": "summarizer",
"resource.tag": "v1"
}
}Caution
Audit events carry actor identity fields, including actor.subject, actor.email, actor.name, actor.roles, and approval.submitter. These fields can contain personal or sensitive information. Solo Enterprise for agentregistry never includes secret values, issued tokens, credentials, or full resource payloads in audit events. Downstream retention, access control, and data classification are the responsibility of your audit or SIEM platform.
The following table describes all event fields and their possible values. Fields marked optional are omitted when not applicable.
| Field | Description | Possible values |
|---|---|---|
severityNumber / severityText | OTel log severity. Severity is carried as a numeric code (severityNumber). The severityText field is empty in the wire format. |
|
body | OTel log body. Contains free-text failure details. This field is empty on success. | string |
scope | OTel logger scope. The scope includes the type of event that occurred. |
|
log.record.uid | Unique log record ID for downstream deduplication. | string |
event.name | Name of the event that occurred. The schema uses the agentregistry.audit prefix on event names and is designed to be friendly for Security Information and Event Management (SIEM) platforms such as Splunk, Microsoft Sentinel, or IBM QRadar. These platforms can ingest the OTel log records directly and query or alert on them without custom parsing rules. For details about the event, see the event.activity and event.action fields. |
|
event.schema_version | Schema version. | v1 (current schema version) |
event.activity | Type of activity. This field determines the OTel scope and the additional fields that are present on the event. For details about the action that was performed during the event, see the event.action field. |
|
event.action | Action that was performed. |
|
actor.subject | Stable actor identity. |
|
actor.type | Type of actor that performed the action. The type is recorded separately from the actor.subject field so that an action that was performed by a user where the JWT’s sub claim is set to system is still classified as a user action, and not a system activity. |
|
actor.roles | Optional. Mapped RBAC role from the OIDC session. | string array |
actor.email | Optional. Email claim from the OIDC session. | string |
actor.name | Optional. Name or preferred username from the OIDC session. | string |
resource.kind | The kind of registry resource that was involved in the event. |
|
resource.namespace | Resource namespace. Represents a logical grouping of resources in the registry catalog. | string |
resource.name | Resource name. | string |
resource.tag | Optional. Resource tag for the referenced resource, such as the version or deployed environment. | string |
resource.uid | Optional. External identifier when known. | string |
event.correlation_id | Optional. Groups related events that share a logical cause, such as all resources applied during a single deployment. | string |
event.dry_run | Optional. Present only when the request simulated a change without committing it. | true: The request represents a dry run. |
error.type | Optional. Stable classifier for non-success events. Omitted on success. |
|
approval.id | Optional. approval events only. Approval identity, including tag when present. | string |
approval.state | Optional. approval events only. Current approval state. | pending — The request has been submitted and is awaiting a decision.approved — The request was approved.revoked — An approved decision was revoked.withdrawn — The request was withdrawn by the submitter. |
approval.submitter | Optional. approval events only. Subject that originally submitted the approval request. | string |
authz.reason | Optional. authorization events only. Reason for the authorization outcome. |
|
target_resource.runtime | Optional. applied_resource events only. Type of runtime that deployed the registry resource. |
|
target_resource.api_group | Optional. applied_resource events only. Kubernetes API group when the downstream resource is a Kubernetes object. | string |
target_resource.kind | Optional. applied_resource events only. Kind of the downstream resource that was deployed to the runtime. |
|
target_resource.namespace | Optional. applied_resource events only. Namespace of the downstream resource. | string |
target_resource.name | Optional. applied_resource events only. Name of the downstream resource. | string |
target_resource.uid | Optional. applied_resource events only. External UID, ARN, or provider ID of the downstream resource. | string |
Other configurations
Route scopes to different backends
Because audit.resource_activity and audit.authz are separate OTel instrumentation scopes, you can route them to different backends. For example, you might want to send lifecycle events to one audit platform and authorization decisions to a separate log aggregator with a longer retention policy.
Deploy a custom OTel Collector with two pipelines that share the same otlp receiver. Each pipeline uses a filter processor to drop records that do not belong to its scope, and exports to its own destination.
receivers:
otlp:
protocols:
grpc:
endpoint: "0.0.0.0:4317"
processors:
filter/resource_activity:
error_mode: ignore
logs:
log_record:
- 'instrumentation_scope.name != "audit.resource_activity"'
filter/authz:
error_mode: ignore
logs:
log_record:
- 'instrumentation_scope.name != "audit.authz"'
exporters:
otlp/siem:
endpoint: "siem.namespace.svc.cluster.local:4317"
otlp/log_aggregator:
endpoint: "loki.namespace.svc.cluster.local:4317"
service:
pipelines:
logs/resource_activity:
receivers: [otlp]
processors: [filter/resource_activity]
exporters: [otlp/siem]
logs/authz:
receivers: [otlp]
processors: [filter/authz]
exporters: [otlp/log_aggregator]Make sure to add the collector’s endpoint in the audit.destination.otlp.endpoint Helm field so that the registry server or relay collector forward event streams to this collector. The collector fans out incoming records to both audit pipelines automatically.
Forward events to multiple destinations
To send all audit events to more than one backend at the same time, such as a SIEM platform for alerting and a log archive for long-term retention, list multiple exporters in the same pipeline as shown in the following OTel configuration.
receivers:
otlp:
protocols:
grpc:
endpoint: "0.0.0.0:4317"
exporters:
otlp/siem:
endpoint: "siem.namespace.svc.cluster.local:4317"
otlp/archive:
endpoint: "loki.namespace.svc.cluster.local:4317"
service:
pipelines:
logs:
receivers: [otlp]
exporters: [otlp/siem, otlp/archive]The collector writes each record to every exporter in the list. If one destination is slow or unavailable, it does not block delivery to the other.
Enrich events with cluster metadata
When you aggregate audit logs from multiple clusters into a single SIEM, add a resource attribute such as cluster.name or environment to every event so you can differentiate them in your queries. Use the resource processor to stamp the attributes before forwarding.
receivers:
otlp:
protocols:
grpc:
endpoint: "0.0.0.0:4317"
processors:
resource:
attributes:
- key: cluster.name
value: "prod-us-east-1"
action: upsert
- key: environment
value: "production"
action: upsert
exporters:
otlp/siem:
endpoint: "siem.namespace.svc.cluster.local:4317"
service:
pipelines:
logs:
receivers: [otlp]
processors: [resource]
exporters: [otlp/siem]The upsert action adds the attribute if it is absent and overwrites it if already present. Set the values to match your cluster and environment before deploying.