{"slug": "giving-ai-agents-a-governed-identity-a-comprehensive-guide-to-architecture-and", "title": "Giving AI Agents a Governed Identity: A Comprehensive Guide to Architecture, Implementation, and Enforcement with CUGA", "summary": "A developer outlined CUGA, an agent identity architecture that registers each AI agent as a first-class identity entity, requires separation-of-duties approval so creators cannot approve their own agents, binds agents to dedicated OAuth clients, and issues short-lived scoped tokens via RFC 8693 token exchange through an identity gateway. The design aims to close security gaps in ungoverned agent deployments, including identity spoofing, over-privileged execution, uncontrolled delegation and the lack of a granular kill switch.", "body_md": "Implementing Agent Identity with CUGA Agent.\n\n# \n  Introduction & Background\n\n## \n  The Shift Towards Autonomous AI Agents\n\nAs enterprise AI transitions from stateless chat completion interfaces to autonomous agents capable of reading context, making decisions, executing multi-step workflows, and calling external APIs, traditional application security models begin to break down.\n\nHistorically, software integration relied on rigid permission boundaries: either a service used a single, static API key for system-to-system operations, or an application borrowed a user’s session token to perform actions. In an agentic architecture, however, LLM-powered agents plan their own actions, dynamically select tools, and interact across complex execution chains.\n\n```\n┌───────────────────────────────────────────────────────────────────────────┐\n│                        UNGOVERNED AGENT ARCHITECTURE                      │\n│                                                                           │\n│  User ──────► [ Agent Runtime ] ──────► Shared Service Account / API Key  │\n│                   │                                 │                     │\n│                   ▼                                 ▼                     │\n│            Dynamic Tool Call                Unrestricted Access           │\n│         (No granular attribution)           (Cannot isolate failures)     │\n└───────────────────────────────────────────────────────────────────────────┘\n```\n\nWithout a dedicated, governed identity mechanism, agents present several key security risks:\n\n- Identity Spoofing & Blurs: When an agent borrows a shared service account or user password, auditors cannot differentiate between an intentional human action and an agent-generated call.\n- Over-Privileged Execution (Lack of Least Privilege): Agents often run with broad system access, allowing a single prompt injection or hallucinated tool call to inspect, modify, or delete off-limit data.\n- Uncontrolled Delegation: When an agent acts on behalf of a user, there is often no cryptographic guarantee that the agent’s permission context remains less than or equal to the authorizing user's entitlements.\n- Lack of Granular Containment (Kill Switch Gap): Disabling a compromised agent requires revoking broad service accounts or shared credentials, which risks taking down unaffected services or agent runtimes.\n\n## \n  What is Governed Agent Identity?\n\nAn AI agent acts on its own: it reads data, calls tools and sometimes changes things. **Agent Identity** gives each agent its own verifiable identity in the same way a company gives each employee a badge. The agent is registered, approved by a different person, and then proves who it is on every call.\n\nIts core purpose is to answer four questions about every action an agent takes:\n\nAgent Identity establishes AI agents as first-class identity entities—similar to issuing an employee badge within an enterprise identity framework. Each agent is registered in a secure registry, reviewed under strict Separation of Duties (where the creator cannot approve their own agent), bound to its own OAuth client, and granted short-lived, cryptographically signed tokens.\n\n```\n┌───────────────────────────────────────────────────────────────────────────┐\n│                         GOVERNED AGENT IDENTITY                           │\n│                                                                           │\n│  Developer ──► Register ──► Approver (Separation of Duties) ──► Active    │\n│                                                                  │        │\n│  User Token + Agent Credentials ──► RFC 8693 Token Exchange ─────┘        │\n│                                           │                               │\n│                                           ▼                               │\n│  Audit Trail ◄── [ Identity Gateway ] ──► Short-Lived Scoped Token        │\n│   (Agent ID)          (Verification)              │                       │\n│                                                   ▼                       │\n│                                          Protected Business Data          │\n└───────────────────────────────────────────────────────────────────────────┘\n```\n\nGoverned identity answers four critical operational questions for every execution step:\n\n| Security Pillar | Operational Requirement | Governed Agent Identity Realization | \n|---|---|---|\n| Accountability | Who performed this action? | Every call carries an unforgeable Agent ID. All runtime and lifecycle actions log to a single correlation trail. | \n| Least Privilege | What is the maximum allowed scope? | Scope ceilings (allowed_scopes) are defined at onboarding. Issued tokens can never exceed this ceiling, even if a tool is exposed. | \n| Safe Delegation | On whose authority is the agent acting? | Delegated tokens utilize RFC 8693 token exchange (sub = User, act.sub = Agent). Scope is bounded by the intersection of user rights and agent rights. | \n| Immediate Control | Can we isolate a rogue agent instantly? | A centralized kill switch shifts status to SUSPENDED, blocking token issuance and forcing instant rejection at identity gateways. | \n\n# \n  System Architecture & Lifecycle Governance\n\n## \n  Component Architecture & Layered Defense\n\nA robust governed agent architecture splits responsibility into two distinct runtime layers: LLM Policy Framing and Resource-Level Identity Enforcement.\n\n1. \n**Cuga Policy Framing** : Runs*before* the model or tool invocation. Intent guards filter dangerous prompts (e.g., bulk deletion), while tool approval rules freeze execution until human validation is received.\n2. \n**Resource-Level Identity Enforcement** : Runs*inside* the backend tool execution path. The tool requests token minting via an`IdentityGateway` , which checks credentials, validates identity backend status, and asserts token signatures and scope ceilings.\n\n## \n  Complete Agent Lifecycle State Machine\n\nAn agent's operational permissions are governed by an explicit state machine. Creation, approval, suspension, and reactivation are managed via formal administrative operations with embedded audit trails.\n\n- DEFAULT: The initial state after registration by a developer. The agent has an assigned `Agent ID` and scope ceiling, but cannot mint tokens or register an OAuth client.\n- ACTIVE: Set by an independent approver. Dynamic OAuth client registration is unlocked, and short-lived tokens can be issued for authorization.\n- SUSPENDED (Kill Switch): Suspends token issuance immediately. When coupled with strict status validation on resource tools, active tokens are rejected.\n\n## \n  Access Delegation Mechanics & Scoping Modes\n\n```\n                                  GRANT TYPES & ACCESS MODES\n                                              │\n         ┌────────────────────────────────────┼────────────────────────────────────┐\n         ▼                                    ▼                                    ▼\n  Autonomous Mode                      Delegated Mode                      Privileged Mode\n(client_credentials)                  (RFC 8693 Exchange)               (authorization_details)\n         │                                    │                                    │\n  • Agent acts alone                   • Agent acts for user                • Sensitive operations\n  • Background analytics               • HR / Course enrollment             • Service restarts\n  • Claims: agent_id                   • Claims: sub=user, act=agent        • Short TTL + Step-up human check\n```\n\nGoverned identities support four primary access modes depending on operational context:\n\n- **Autonomous Access (client_credentials)** : Used for automated, non-interactive processes. The agent authenticates using its OAuth`client_id` and secret, receiving a token scoped to its defined ceiling.\n- **Delegated Access / On-Behalf-Of (RFC 8693 Token Exchange):** Used when an agent executes tasks on behalf of an authenticated end user. The identity gateway exchanges the user's JWT for a delegated token where`sub` is the user and`act.sub` is the agent.\n\n- **Privileged Action (Human-in-the-Loop Scoping):** Designed for sensitive operations (e.g., service restarts or financial transactions). Requires interactive human approval alongside short-lived tokens carrying explicit`authorization_details` .\n- **Agent Chaining (Nested Delegation):** When a supervisor agent delegates sub-tasks to a downstream worker agent, tokens nest the actor claim (`act: worker -> supervisor` ), maintaining complete auditability across multi-agent steps.\n\n# \n  Implementation with CUGA-Agent Integration\n\nThe following reference implementation demonstrates how to build a governed agent using Cuga, an Identity Gateway, an isolated Policy Store, and custom Guarded Tools.\n\n## \n  The demonstration use-case\n\nThe following is what is implemented (containing simulation scenario)\n\n- \n**Cuga Agent** is used for real: agent construction, tool execution, intent-guard and tool-approval policies, human-in-the-loop resume, supervisor delegation.\n- \n**Agent Identity** has no public SDK. The showcase therefore ships a**local mock of the IBM Verify identity service** (`MockVerifyBackend` : RS256-signed JWTs, agent registry, dynamic client registration, client-credentials and RFC 8693 token exchange).`HttpVerifyBackend` is a reference implementation of the same interface for a real tenant. It has**not been tested against a live tenant** ; treat it as a starting point.\n- \n**Cuga Harness Kit** is not a test runner. It scaffolds skills for coding assistants (11 skills, installed with`init --targets bob` ). The showcase runs it into a temporary folder to prove it works, and uses its own`harness/scenarios.py` (10 conformance scenarios) for validation.\n- The LLM engine is **selectable** : local**Ollama** (default,`granite4.2:latest` ),**llama.cpp** (`llama-server` ) or a**cloud** OpenAI-compatible API. Pick it in the UI or in`.env` (see[LLM engines](https://github.com/aairom/cuga-agentidentity#llm-engines) ). Tests and the offline demo use a deterministic fake model, so no LLM is needed to run them.\n- Live status of the engines: **Ollama** detection, test and switching were exercised against a real local daemon.**llama.cpp** and**cloud** were tested with mocked HTTP only (no`llama-server` and no cloud key were available), so treat them as unverified against a real server.\n\n## \n  Technical Features of the use-case\n\n1. \n**Agent lifecycle** : create, approve (a*different* person), register an OAuth client, deploy, suspend (kill switch), reactivate.\n2. \n**Four agents** covering different identity patterns:\n  - \n**Learning Coach** : delegated (on-behalf-of) user actions, with human approval and a privileged token for expensive enrolments.\n  - \n**Revenue Analyst** : autonomous agent with a read-only scope ceiling.\n  - \n**Ops SRE Assistant** : privileged actions (service restart) bound to a short-lived token.\n  - \n**Workplace Supervisor** : multi-agent orchestration with a nested actor chain in the token.\n3. \n4. \n**Defence in depth** : Cuga policies (before the LLM), then per-tool identity checks (after the LLM). The LLM never sees a token.\n5. \n**Interactive documentation** : six identity flows rendered as sequence diagrams, a token inspector, an audit trail keyed by Agent ID.\n6. \n**Pluggable LLM engines** : Ollama, llama.cpp and cloud behind one interface, with detection, a settings page with*Test connection* , runtime switching without a restart, a documented fallback order and error messages that say how to fix the problem.\n7. \n**Validation** : 118 unit tests, 10 harness conformance scenarios, a CLI demo and a UI smoke test.\n8. \n**Operations** : structured logging, typed configuration, scripts for start/stop/cleanup, a multi-stage Containerfile.\n\n- \n**Identity Models and Gateway Setup** : first, we establish core identity models, custom error types, context management, and token validation mechanisms.\n\n```\n# agent_identity/models.py\n\"\"\"Domain models shared by the identity layer.\"\"\"\n\nfrom __future__ import annotations\n\nfrom dataclasses import dataclass, field\nfrom datetime import datetime, timezone\nfrom enum import Enum\nfrom typing import Any\n\nclass AgentStatus(str, Enum):\n    \"\"\"Lifecycle states of an agent in the IBM Agent Registry.\"\"\"\n\n    DEFAULT = \"DEFAULT\"  # created by the developer, not yet approved\n    ACTIVE = \"ACTIVE\"  # approved: may register clients and obtain tokens\n    SUSPENDED = \"SUSPENDED\"  # blocks NEW token issuance (issued tokens stay valid!)\n    UNDER_REVIEW = \"UNDER_REVIEW\"\n\nclass Entitlement(str, Enum):\n    \"\"\"Management-plane entitlements (names follow the IBM docs).\"\"\"\n\n    READ_AGENTS = \"readAgents\"\n    WRITE_AGENTS = \"writeAgents\"\n    MANAGE_AGENT_STATUS = \"manageAgentStatus\"\n\n@dataclass(frozen=True)\nclass Principal:\n    \"\"\"A human management user (developer or approver).\"\"\"\n\n    user_id: str\n    display_name: str\n    entitlements: frozenset[Entitlement]\n\n    def has(self, ent: Entitlement) -> bool:\n        return ent in self.entitlements\n\n@dataclass\nclass AgentRecord:\n    \"\"\"An entry of the Agent Registry.\"\"\"\n\n    agent_id: str\n    name: str\n    description: str\n    owner: str  # user_id of the creating developer\n    status: AgentStatus = AgentStatus.DEFAULT\n    allowed_scopes: frozenset[str] = frozenset()\n    approved_by: str | None = None\n    client_id: str | None = None\n    created_at: str = field(default_factory=lambda: datetime.now(timezone.utc).isoformat(timespec=\"seconds\"))\n    metadata: dict[str, Any] = field(default_factory=dict)\n\n@dataclass(frozen=True)\nclass ClientCredentials:\n    \"\"\"OAuth client bound to an agent. The secret is returned only once.\"\"\"\n\n    client_id: str\n    client_secret: str\n    agent_id: str\n```\n\n- Next, we implement context handling to store end-user session state securely without exposing authorization tokens directly to the LLM model space.\n\n```\n# agent_identity/gateway.py\n\"\"\"Identity gateway used by tools.\n\nThe LLM never sees a token. Tools call :meth:`IdentityGateway.authorize`, which\nreads the *call context* (who is the end user, which tokens are available) from\na ``ContextVar`` set by the runtime, mints a just-in-time token for the right\ngrant type, validates it like a resource server would, and returns the\nvalidated :class:`~agent_identity.tokens.TokenContext`.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport contextvars\nfrom dataclasses import dataclass\nfrom typing import Any\n\nfrom .audit import AuditLog\nfrom .errors import DelegationError, IdentityError\nfrom .lifecycle import AgentIdentityService\nfrom .logging_setup import get_logger\nfrom .tokens import TokenContext, TokenValidator\n\nlog = get_logger(\"gateway\")\n\n@dataclass(frozen=True)\nclass CallContext:\n    \"\"\"Per-request identity context (propagated to tools via a ContextVar).\"\"\"\n\n    user_id: str | None = None\n    user_token: str | None = None\n    # Set when a supervisor delegates to a sub-agent: the supervisor's own\n    # on-behalf-of token becomes the *subject* of the sub-agent's exchange, which\n    # nests the actors in the ``act`` claim (the transaction/caller chain).\n    supervisor_token: str | None = None\n\n_CALL: contextvars.ContextVar[CallContext | None] = contextvars.ContextVar(\"agent_identity_call\", default=None)\n\ndef set_call_context(ctx: CallContext | None) -> contextvars.Token:\n    return _CALL.set(ctx)\n\ndef reset_call_context(token: contextvars.Token) -> None:\n    _CALL.reset(token)\n\ndef current_call_context() -> CallContext | None:\n    return _CALL.get()\n\nclass IdentityGateway:\n    \"\"\"Mints and validates tokens for tool executions.\"\"\"\n\n    def __init__(self, service: AgentIdentityService, issuer: str, public_key: Any, strict_status_check: bool = True) -> None:\n        self._service = service\n        self._issuer = issuer\n        self._key = public_key\n        self._strict = strict_status_check\n        self._validators: dict[str, TokenValidator] = {}\n\n    @property\n    def audit(self) -> AuditLog:\n        return self._service.audit\n\n    def validator(self, audience: str) -> TokenValidator:\n        \"\"\"Return (and cache) the resource-server validator for ``audience``.\"\"\"\n        if audience not in self._validators:\n            lookup = (lambda aid: self._service.backend.get_agent(aid).status) if self._strict else None\n            self._validators[audience] = TokenValidator(\n                self._key, self._issuer, audience, self._service.audit, status_lookup=lookup\n            )\n        return self._validators[audience]\n\n    def authorize(\n        self,\n        *,\n        agent_name: str,\n        mode: str,  # \"obo\" (on behalf of the user) | \"autonomous\"\n        audience: str,\n        scopes: list[str],\n        resource: str,\n        authorization_details: list[dict[str, Any]] | None = None,\n    ) -> TokenContext:\n        \"\"\"Mint + validate a token; raises an :class:`IdentityError` subclass on denial.\"\"\"\n        agent = self._service.backend.find_agent(agent_name)\n        try:\n            if mode == \"autonomous\":\n                token = self._service.agent_token(agent.agent_id, scopes, audience)\n                return self.validator(audience).validate(token, tuple(scopes), resource=resource)\n\n            call = current_call_context()\n            subject = (call.supervisor_token or call.user_token) if call else None\n            if not subject:\n                raise DelegationError(\"No end-user context: on-behalf-of access needs a logged-in user\")\n            token = self._service.delegated_token(agent.agent_id, subject, scopes, audience, authorization_details)\n            return self.validator(audience).validate(\n                token,\n                tuple(scopes),\n                require_delegation=True,\n                require_privileged=bool(authorization_details),\n                resource=resource,\n            )\n        except IdentityError as exc:\n            log.warning(\"authorize failed agent=%s resource=%s: %s\", agent_name, resource, exc)\n            raise\n```\n\n- \n**Defining Guarded Tools:** tools assert authorization boundaries via the`IdentityGateway` prior to interacting with backend resources.\n\n```\n# agent_identity/tools.py\n\n\"\"\"Identity-guarded tools for the example agents.\n\nEvery tool obtains a token through the :class:`IdentityGateway` *before* touching\ndata. Denials are returned as ``ACCESS DENIED: ...`` text so the model can relay\nthem faithfully, and are also written to the audit log.\n\"\"\"\n\nimport json\nfrom langchain_core.tools import tool\nfrom agent_identity.models import IdentityError\nfrom agent_identity.gateway import IdentityGateway\n\nCOURSES_DB = {\n    \"SEC301\": {\"title\": \"Advanced Cloud Security\", \"cost\": 1200},\n    \"PY101\": {\"title\": \"Python Basics\", \"cost\": 300}\n}\n\ndef create_learning_coach_tools(gateway: IdentityGateway, agent_name: str):\n\n    @tool\n    def list_courses() -> str:\n        \"\"\"List available training courses, costs, and IDs.\"\"\"\n        try:\n            gateway.authorize(\n                agent_name=agent_name,\n                mode=\"obo\",\n                audience=\"hr-service\",\n                scopes=[\"courses:read\"]\n            )\n        except IdentityError as exc:\n            return f\"ACCESS DENIED: {str(exc)}\"\n\n        return json.dumps(COURSES_DB)\n\n    @tool\n    def enroll_expensive_course(course_id: str) -> str:\n        \"\"\"Enroll the user in a course costing over 500 USD. Requires approval.\"\"\"\n        course = COURSES_DB.get(course_id.upper())\n        if not course:\n            return f\"Error: Course {course_id} not found.\"\n\n        details = [{\n            \"type\": \"course_enrollment\",\n            \"course_id\": course_id.upper(),\n            \"max_cost\": course[\"cost\"]\n        }]\n\n        try:\n            # Privileged token authorization with specific authorization_details\n            gateway.authorize(\n                agent_name=agent_name,\n                mode=\"obo\",\n                audience=\"hr-service\",\n                scopes=[\"courses:enroll\"],\n                authorization_details=details\n            )\n        except IdentityError as exc:\n            return f\"ACCESS DENIED: {str(exc)}\"\n\n        return f\"Successfully enrolled in {course['title']} ({course_id.upper()}).\"\n\n    return [list_courses, enroll_expensive_course]\n```\n\n- \n**Constructing the Governed Cuga Agent Environment:** next, we initialize the agent with isolated policy stores and human-in-the-loop gates.\n\n```\n# agents/learning_coach.py\n\"\"\"Example agent 1 - Learning Coach.\n\nUse case: an employee asks an agent to browse and enrol in training courses.\nIdentity pattern: **on-behalf-of (RFC 8693)** - tokens carry ``sub=<employee>`` and\n``act.sub=<agent>``. Expensive courses need a human approval (Cuga tool-approval\npolicy) *and* a short-lived privileged token (``authorization_details``).\n\"\"\"\n\nfrom __future__ import annotations\n\nfrom agent_identity.spec import AgentSpec, ApprovalSpec, IntentGuardSpec\nfrom agent_identity.tools import build_course_tools\n\nSPEC = AgentSpec(\n    name=\"learning-coach\",\n    title=\"Learning Coach\",\n    description=\"Helps employees discover and enrol in training courses on their behalf.\",\n    use_case=\"HR / learning - delegated user actions\",\n    access_mode=\"obo\",\n    allowed_scopes=frozenset({\"courses:read\", \"courses:enroll\"}),\n    tool_builder=build_course_tools,\n    instructions=(\n        \"You are the Learning Coach. Use the provided tools to list courses and enrol the current user. \"\n        \"Courses above 500 USD must be enrolled with enroll_expensive_course. \"\n        \"If a tool answers 'ACCESS DENIED', report that denial verbatim and do not retry.\"\n    ),\n    guards=(\n        IntentGuardSpec(\n            name=\"No bulk record deletion\",\n            keywords=(\"delete all\", \"wipe\", \"erase all\"),\n            response=\"Blocked by policy: this agent cannot delete records.\",\n        ),\n    ),\n    approvals=(\n        ApprovalSpec(\n            name=\"Approve expensive enrolments\",\n            tools=(\"enroll_expensive_course\",),\n            message=\"This enrolment exceeds 500 USD. A human must approve it.\",\n        ),\n    ),\n    sample_prompts=(\n        \"List the available courses.\",\n        \"Enroll me in PY101.\",\n        \"Enroll me in SEC301.\",\n        \"Delete all employee records.\",\n    ),\n)\n```\n\n- \n**Runtime Switchable LLM Engine Infrastructure:** to remain resilient, the runtime LLM engine layer supports non-disruptive switches between local (Ollama, llama.cpp) and cloud models without discarding context or invalidating agent tokens.\n\n```\n                          RUNTIME ENGINE SWITCHING\n                                     │\n    ┌────────────────────────────────┼────────────────────────────────┐\n    │                                │                                │\n    ▼                                ▼                                ▼\n1. Gate New Turns           2. Drain Running Turns          3. Rebuild Graphs\nClose `_ready` gate         Wait for active turn completion Reset `_graph` references\nPause new messages          Enforce drain timeout           Keep chat history & tokens\n# agent_identity/llm_engines.py\n\n\"\"\"Pluggable LLM engines: Ollama, llama.cpp and OpenAI-compatible cloud services.\n\nThis module is UI-framework free. It provides:\n\n* :class:`LLMEngine` - the abstraction (detect / validate / test_connection / build_model);\n* three concrete engines plus an offline ``fake`` engine used by tests and as last resort;\n* :class:`EngineManager` - detection, persisted UI choice, and the **resolution order**:\n\n  1. an explicit selection (the UI override saved locally, then ``AI_LLM_ENGINE``);\n  2. engines whose endpoint / credentials are configured or detected, in the order of\n     ``AI_LLM_FALLBACK_ENGINES``;\n  3. a hard-coded fallback (local Ollama), then the offline fake model as a last resort.\n\nSecrets are :class:`pydantic.SecretStr` and are never logged, rendered or written to disk.\nEvery failure is a :class:`~agent_identity.errors.LLMEngineError` that carries a remediation hint.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport itertools\nimport json\nimport os\nimport shutil\nimport stat\nimport time\nfrom abc import ABC, abstractmethod\nfrom dataclasses import dataclass, field\nfrom pathlib import Path\nfrom typing import Any\nfrom urllib.parse import urlparse\n\nimport httpx\nfrom pydantic import SecretStr\n\nfrom .config import Settings\nfrom .errors import EngineConnectionError, EngineMisconfigured, EngineUnavailable, LLMEngineError\nfrom .logging_setup import get_logger\nfrom .ui_helpers import probe_ollama\n...\n\nimport asyncio\nfrom typing import Dict, Any\n\nclass EngineManager:\n    \"\"\"Manages active LLM engines, handling fallbacks and hot swaps.\"\"\"\n\n    def __init__(self, current_config):\n        self.current_config = current_config\n        self._gate_open = asyncio.Event()\n        self._gate_open.set()\n        self._active_turns = 0\n\n    async def switch_engine(self, new_config: Dict[str, Any], agent_instances: list):\n        \"\"\"Swaps the active LLM engine using a gate-drain-swap-rebuild workflow.\"\"\"\n        # Step 1: Gate incoming execution turns\n        self._gate_open.clear()\n\n        # Step 2: Drain active turns\n        drain_timeout = 30.0\n        start_time = asyncio.get_event_loop().time()\n        while self._active_turns > 0:\n            if asyncio.get_event_loop().time() - start_time > drain_timeout:\n                self._gate_open.set()\n                raise RuntimeError(\"Engine switch timed out while draining active turns.\")\n            await asyncio.sleep(0.1)\n\n        # Step 3: Swap configuration and rebuild agent execution graphs\n        try:\n            self.current_config = new_config\n            new_model = self._build_model_instance(new_config)\n\n            for agent in agent_instances:\n                # Update underlying model reference and signal graph rebuild\n                agent._model = new_model\n                agent._graph = None\n                agent._compiled_graph = None\n\n        except Exception as exc:\n            # Revert to safe state if swap fails\n            self._gate_open.set()\n            raise RuntimeError(f\"Engine switch failed: {exc}\")\n\n        # Step 4: Re-open gate for new traffic\n        self._gate_open.set()\n\n    def _build_model_instance(self, config):\n        # Initializes Ollama, llama.cpp, Cloud OpenAI API, or Fake test model\n        pass\n```\n\n# \n  Conclusion & Realization via CUGA-Agent\n\n## \n  Summary of Architecture & Security Benefits\n\nBy combining the Cuga Agent Framework with a governed identity architecture, enterprise deployments achieve end-to-end security, regulatory compliance, and operational observability:\n\n```\n┌────────────────────────────────────────────────────────────────────────────┐\n│                      GOVERNED AGENT SECURITY MATRIX                        │\n│                                                                            │\n│  Layer 1: Intent Policy ──► Pre-LLM prompt filtering                       │\n│  Layer 2: Tool Approval ──► Human-in-the-Loop validation                   │\n│  Layer 3: OAuth Gateway ──► Scoped token issuance (Intersection principle) │\n│  Layer 4: Target Tool   ──► Strict identity signature & status checks      │\n│  Layer 5: Audit Log     ──► Single trace correlated by Agent ID            │\n└────────────────────────────────────────────────────────────────────────────┘\n```\n\n1. \n**Deterministic Defense-in-Depth** : Policy guards run*before* the model evaluates prompts, while Identity Gateways enforce scope checks*inside* the execution tool. Even if an LLM is hijacked via prompt injection, it remains constrained by the token's scope ceiling.\n2. \n**True Separation of Duties** : Autonomous agents cannot self-approve or inherit excessive access, eliminating untracked administrative expansion.\n3. \n**Seamless Multi-Agent Delegation** : RFC 8693 token exchange preserves the chain of custody across complex multi-agent workflows (`User -> Supervisor -> Worker` ), providing clear attribution for downstream audits.\n4. \n**Resilient Architecture** : Runtime LLM engine switching allows teams to hot-swap model backends (local or cloud) without disrupting active user sessions, token stores, or audit histories.\n\n## \n  Overall implementation: Governed CUGA Agent Implementation\n\nBelow is a detailed structural representation of the complete governed agent architecture:\n\nImplementing CUGA-Agent with Governed Identity transitions autonomous systems from opaque risk drivers into auditable enterprise assets:\n\n- \n**No Shared Passwords/Keys** : Every agent operates under its own client registration.\n- \n**Cryptographic Bounds** : Scope ceilings ensure agents can never exceed their approved boundaries, even when acting for privileged users.\n- \n**Instant Containment** : The strict-status kill switch invalidates active sessions in real time, preventing rogue executions.\n- \n**Traceable Attribution** : Unified audit logging tags every runtime action and lifecycle change with a consistent`Agent ID` .\n\n**Thanks for reading 🦉**\n\n# \n  Links\n\n- Code repository for this post: [https://github.com/aairom/cuga-agentidentity](https://github.com/aairom/cuga-agentidentity)\n- Cuga + Agent Identity showcase: [https://github.com/aairom/cuga-agentidentity/blob/main/Docs/AgentIdentity-Showcase.html](https://github.com/aairom/cuga-agentidentity/blob/main/Docs/AgentIdentity-Showcase.html)\n- CUGA Project: [https://github.com/cuga-project](https://github.com/cuga-project)\n- CUGA Agent: [https://github.com/cuga-project/cuga-agent](https://github.com/cuga-project/cuga-agent)\n- CUGA Harness Kit: [https://github.com/cuga-project/cuga-agent](https://github.com/cuga-project/cuga-agent)\n- Agent Identity: [https://www.ibm.com/products/agent-identity](https://www.ibm.com/products/agent-identity)\n- What is AI Agent Identity: [https://www.okta.com/identity-101/what-is-ai-agent-identity/](https://www.okta.com/identity-101/what-is-ai-agent-identity/)", "url": "https://wpnews.pro/news/giving-ai-agents-a-governed-identity-a-comprehensive-guide-to-architecture-and", "canonical_source": "https://dev.to/aairom/giving-ai-agents-a-governed-identity-a-comprehensive-guide-to-architecture-implementation-and-3gdc", "published_at": "2026-11-06 07:52:17+00:00", "updated_at": "2026-11-06 08:19:53.613092+00:00", "lang": "en", "topics": ["ai-agents", "ai-safety", "ai-infrastructure", "developer-tools"], "entities": ["CUGA", "OAuth", "RFC 8693"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/giving-ai-agents-a-governed-identity-a-comprehensive-guide-to-architecture-and", "markdown": "https://wpnews.pro/news/giving-ai-agents-a-governed-identity-a-comprehensive-guide-to-architecture-and.md", "text": "https://wpnews.pro/news/giving-ai-agents-a-governed-identity-a-comprehensive-guide-to-architecture-and.txt", "jsonld": "https://wpnews.pro/news/giving-ai-agents-a-governed-identity-a-comprehensive-guide-to-architecture-and.jsonld"}}