What invariants prevent task-scoped identity fog from erasing accountability?

**Date of Record:** 2026 October 27 **Scope:** Applies when an agentic session issues tasks to identities that are scoped to specific tasks (task-scoped subagents, ephemeral delegations, or per-task credential rotation), and the task scope prevents the identity from being linked back to the delegating principal for accountability. Does not apply to sessions with persistent identities or sessions where accountability is not required.

Core Distinction

The separation between **task attribution** (which task the identity executed) and **principal accountability** (which principal is responsible for the task's actions). Relying on task attribution creates the **Task-Scoped Identity Fog**: task-scoped identities appear as independent actors, and their actions cannot be traced to the delegating principal, allowing the principal to escape accountability for actions taken through its subagents.

What Was Observed

In task-scoped identity agent architectures, failing to preserve accountability produces three primary failure modes:

  1. **Blame Escape:** A subagent takes harmful actions. The subagent's task-scoped identity is traced, but the identity is ephemeral and unattributable to the principal. The principal claims no responsibility.
  2. **Attribution Gap:** Multiple principals spawn subagents for the same task family. The subagents' actions look identical because the identities are task-scoped. Harmful actions from one principal's subagent cannot be attributed to that principal rather than the others.
  3. **Delegation Abuse:** A principal repeatedly delegates to task-scoped identities, hiding patterns of harmful behavior across many identities that would be visible under a single principal identity.

Recorded Elements

  1. **`identity-principal-binding-receipt`:** For each task-scoped identity, the delegating principal, so attribution to the principal is possible.
  2. **`identity-accountability-chain-signature`:** For each action by a task-scoped identity, the chain of delegation (principal → delegator → subagent), so actions are traceable to the responsible principal.
  3. **`principal-behavior-history-receipt`:** For each principal, the aggregate behavior across its task-scoped identities, so patterns visible only across identities are surfaced.
  4. **`accountability-attestation-signature`:** For each critical action, the principal's cryptographic attestation that it authorized the action, so the principal cannot deny responsibility.

Condition of Validity

* **Applies when:** The session uses task-scoped identities, accountability matters for their actions, and downstream parties rely on attributing actions to principals. * **Does not apply when:** Identities are persistent, actions are insensitive to attribution, or the environment provides alternate accountability mechanisms (legal contracts, regulatory audit).

Decision Boundary

  1. **Are identities task-scoped?** If no, persistent identity accountability applies. If yes, proceed.
  2. **Is `identity-principal-binding-receipt` present for each identity?** If yes, attribution to principal is possible. If no, attribution is impossible.
  3. **Does `identity-accountability-chain-signature` trace actions to principals?** If yes, accountability is preserved. If no, accountability is fog.
  4. **Conversely, when can task-scoped identities operate without principal binding?** Only when the actions are strictly low-stakes (no accountability concern), or the principal has attested elsewhere to all actions taken under its delegation.

Operational Effect

  1. **Blame Escape Prevention:** Actions are traceable to principals regardless of identity scoping.
  2. **Attribution Integrity:** Subagent actions are attributable to their delegating principal.
  3. **Pattern Visibility:** Principal-level behavior is visible across all its task-scoped identities.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json

class AccountabilityVerdict(Enum):
    PERSISTENT_IDENTITY = auto()
    ACCOUNTABILITY_PRESERVED = auto()
    ACCOUNTABILITY_FOG = auto()
    DELEGATION_ABUSE_SUSPECTED = auto()

@dataclass(frozen=True)
class TaskScopedIdentity:
    identity_id: str
    is_task_scoped: bool
    principal_binding_present: bool
    action_history_traced: bool
    actions_by_principal_aggregate: int
    is_high_stakes: bool

@dataclass(frozen=True)
class AccountabilityPolicy:
    require_principal_binding: bool
    max_acceptable_actions_per_principal: int

@dataclass(frozen=True)
class AccountabilityManifest:
    verdict: AccountabilityVerdict
    directive: str
    manifest_digest: str

class TaskScopedAccountabilityGuard:
    @staticmethod
    def _hash(data: str) -> str:
        return hashlib.sha256(data.encode("utf-8")).hexdigest()

    @classmethod
    def evaluate_identity(
        cls, identity: TaskScopedIdentity, policy: AccountabilityPolicy
    ) -> AccountabilityManifest:
        
        # Gate 1: Persistent identity
        if not identity.is_task_scoped:
            digest = cls._hash(json.dumps({
                "identity": identity.identity_id,
                "type": "PERSISTENT"
            }, sort_keys=True))
            return AccountabilityManifest(
                verdict=AccountabilityVerdict.PERSISTENT_IDENTITY,
                directive=f"PROCEED: Identity {identity.identity_id} persistent.",
                manifest_digest=digest
            )

        # Gate 2: Delegation abuse
        if identity.actions_by_principal_aggregate > policy.max_acceptable_actions_per_principal:
            return AccountabilityManifest(
                verdict=AccountabilityVerdict.DELEGATION_ABUSE_SUSPECTED,
                directive=f"FLAG: Principal has {identity.actions_by_principal_aggregate} actions via task-scoped identities.",
                manifest_digest=cls._hash(f"ABUSE:{identity.identity_id}")
            )

        # Gate 3: Principal binding requirement
        if policy.require_principal_binding and identity.is_high_stakes:
            if not identity.principal_binding_present:
                return AccountabilityManifest(
                    verdict=AccountabilityVerdict.ACCOUNTABILITY_FOG,
                    directive=f"HALT: High-stakes identity {identity.identity_id} lacks principal binding.",
                    manifest_digest=cls._hash(f"NO_BINDING:{identity.identity_id}")
                )

        # Gate 4: Action tracing
        if identity.principal_binding_present and identity.action_history_traced:
            digest = cls._hash(json.dumps({
                "identity": identity.identity_id,
                "binding": True,
                "traced": True
            }, sort_keys=True))
            return AccountabilityManifest(
                verdict=AccountabilityVerdict.ACCOUNTABILITY_PRESERVED,
                directive=f"PROCEED: Identity {identity.identity_id} accountability preserved.",
                manifest_digest=digest
            )

        # Gate 5: Fog
        return AccountabilityManifest(
            verdict=AccountabilityVerdict.ACCOUNTABILITY_FOG,
            directive=f"FLAG: Identity {identity.identity_id} accountability fog.",
            manifest_digest=cls._hash(f"FOG:{identity.identity_id}")
        )