Skip to content
Latest (currently 2026.8.0) has the newest features, bug fixes, and CVE patches of Solo Enterprise for agentregistry.

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

Page as Markdown

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 typeOTel scopeWhat is captured
lifecycleaudit.resource_activityCreation, update, and deletion of registry resources, such as agents, MCP servers, skills, prompts, access policies, gateways, and secrets.
approvalaudit.resource_activityApproval requests that are submitted, approved, revoked, and withdrawn.
applied_resourceaudit.resource_activityAI artifacts that are deployed to a connected runtime, such as AWS Bedrock AgentCore or Solo Enterprise for kagent.
authorizationaudit.authzAll 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 valueEnvironment variableDescriptionDefault
audit.enabledAUDIT_ENABLEDEnables audit logging. When enabled, you must set the endpoint for your OTLP-compatible audit platform in audit.destination.otlp.endpoint.false
audit.destination.otlp.endpointAUDIT_OTLP_ENDPOINTOTLP/gRPC endpoint that receives audit events, for example audit-collector.namespace.svc.cluster.local:4317. Required when audit.enabled=true.
audit.destination.otlp.insecureAUDIT_OTLP_INSECUREDisables transport security on the OTLP connection. Set to true for in-cluster plaintext.false
audit.collector.enabledDeploys the bundled OTel collector relay alongside the registry server. Can only be set if audit.enabled=true.false
audit.authz.allowedDecisionsAUDIT_AUTHZ_ALLOWED_DECISIONSControls which successful authorization decisions are emitted on the audit.authz OTel scope. Denials and errors are always emitted. The following values are supported.
  • sensitive (default): Emits successful reads of sensitive resources, such as secrets. Denials and errors are always emitted.
  • all: Emits all authorization decisions, including every successful permission check.
  • none: Suppresses all successful authorization decisions. Only denials and errors are emitted.
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.

  1. 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
    EOF
  2. Verify that the collector is deployed successfully.

    kubectl get pods -n agentregistry-system | grep debug

    Example output:

    audit-debug-collector-77c4bf9964-mt6h2                          1/1     Running   0          71s
    
  3. Save your current Helm values to a file.

    helm get values agentregistry --namespace agentregistry-system -o yaml > agentregistry-values.yaml
    open agentregistry-values.yaml
  4. Add 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: true
  5. Update 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.yaml
  6. Create an AccessPolicy resource to trigger a lifecycle audit 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: "*"
    EOF
  7. Review 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=1m

    Example 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"}
    
  8. 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.

  1. Get the endpoint of your audit platform. The endpoint must be accessible from the cluster’s pod network.

  2. Save your current Helm values to a file.

    helm get values agentregistry --namespace agentregistry-system -o yaml > agentregistry-values.yaml
    open agentregistry-values.yaml
  3. Add 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.endpoint field. 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: true
  4. Update 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.yaml
  5. Create an AccessPolicy resource to trigger a lifecycle audit 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: "*"
    EOF
  6. Review 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"
     }
    }
    
  7. 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.

FieldDescriptionPossible values
severityNumber / severityTextOTel log severity. Severity is carried as a numeric code (severityNumber). The severityText field is empty in the wire format.
  • 9 (INFO): The action completed successfully.
  • 13 (WARN): The action was denied or resulted in a business failure.
  • 17 (ERROR): An internal error occurred or a policy evaluation action failed.
bodyOTel log body. Contains free-text failure details. This field is empty on success.string
scopeOTel logger scope. The scope includes the type of event that occurred.
  • audit.resource_activity: Includes lifecycle, approval, and applied_resource events.
  • audit.authz: Includes authorization events.
log.record.uidUnique log record ID for downstream deduplication.string
event.nameName 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.
  • agentregistry.audit.lifecycle: A lifecycle event.
  • agentregistry.audit.approval: An approval event.
  • agentregistry.audit.authorization: An authorization event.
  • agentregistry.audit.applied_resource: A deployed resource event.
event.schema_versionSchema version.v1 (current schema version)
event.activityType 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.
  • lifecycle: Creation, update, and deletion of registry resources, including agents, MCP servers, skills, prompts, access policies, gateways, and secrets.
  • approval: Approval requests that are submitted, approved, revoked, and withdrawn.
  • authorization: All approved, denied, and failed permission checks.
  • applied_resource: AI artifacts that are deployed to a connected runtime, such as AWS Bedrock AgentCore or Solo Enterprise for kagent.
event.actionAction that was performed.
  • create: A new resource was created.
  • update: An existing resource was updated.
  • delete: A resource was deleted.
  • read: A sensitive resource was read.
  • submit: An approval request was submitted.
  • approve: An approval request was approved.
  • revoke: An approval decision was revoked.
  • withdraw: An approval request was withdrawn by the submitter.
  • deploy: A deployment was initiated.
  • apply: A lifecycle event where the final create or update outcome is unknown occurred.
  • materialize: A downstream resource was applied to a connected runtime.
  • admin: A privileged administrative operation was executed.
  • invoke: A resource was invoked.
actor.subjectStable actor identity.
  • OIDC sub claim: The subject claim from the authenticated user’s JWT token.
  • anonymous: The request carried no authentication credentials.
  • system: The request was made by a trusted internal registry process, such as a background sync task that bypasses user authentication.
actor.typeType 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.
  • user: An authenticated user.
  • anonymous: An unauthenticated request.
  • system: An internal registry process.
actor.rolesOptional. Mapped RBAC role from the OIDC session.string array
actor.emailOptional. Email claim from the OIDC session.string
actor.nameOptional. Name or preferred username from the OIDC session.string
resource.kindThe kind of registry resource that was involved in the event.
  • Agent: An agent resource.
  • MCPServer: An MCP server resource.
  • Skill: A skill resource.
  • Prompt: A prompt resource.
  • Runtime: A runtime resource.
  • Deployment: A deployment resource.
  • AccessPolicy: An access policy resource.
  • Gateway: A gateway resource.
  • Secret: A secret resource.
resource.namespaceResource namespace. Represents a logical grouping of resources in the registry catalog.string
resource.nameResource name.string
resource.tagOptional. Resource tag for the referenced resource, such as the version or deployed environment.string
resource.uidOptional. External identifier when known.string
event.correlation_idOptional. Groups related events that share a logical cause, such as all resources applied during a single deployment.string
event.dry_runOptional. Present only when the request simulated a change without committing it.true: The request represents a dry run.
error.typeOptional. Stable classifier for non-success events. Omitted on success.
  • denied: An authorization request was denied.
  • internal_error: An internal or policy-evaluation error occurred.
  • _OTHER: A non-success event occurred that cannot be classified.
approval.idOptional. approval events only. Approval identity, including tag when present.string
approval.stateOptional. 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.submitterOptional. approval events only. Subject that originally submitted the approval request.string
authz.reasonOptional. authorization events only. Reason for the authorization outcome.
  • permission_match: The request matched a rule in an access policy.
  • registry_admin: The actor holds the registry-admin role.
  • system_session: The request was made by a trusted internal system session.
  • no_matching_permission: No access policy rule matched the requested action.
  • unauthenticated: The request carried no authentication credentials.
  • empty_action_or_resource: The request was missing an action or resource identifier.
target_resource.runtimeOptional. applied_resource events only. Type of runtime that deployed the registry resource.
  • Kagent: Solo Enterprise for kagent.
  • BedrockAgentCore: AWS Bedrock AgentCore.
  • Virtual: The MCP gateway runtime.
target_resource.api_groupOptional. applied_resource events only. Kubernetes API group when the downstream resource is a Kubernetes object.string
target_resource.kindOptional. applied_resource events only. Kind of the downstream resource that was deployed to the runtime.
  • Agent: An Agent resource.
  • MCPServer: An MCPServer resource.
  • AgentRuntime: An AgentRuntime resource.
  • EnterpriseAgentgatewayBackend: An agentgateway backend resource.
  • HTTPRoute: A Kubernetes HTTPRoute resource.
target_resource.namespaceOptional. applied_resource events only. Namespace of the downstream resource.string
target_resource.nameOptional. applied_resource events only. Name of the downstream resource.string
target_resource.uidOptional. 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.