{"record":{"id":"82cfcda5efa01ddf","repo":"github/copilot-sdk","slug":"agent-id-must-be-a-string","errorCode":null,"errorMessage":"agent_id must be a string","messagePattern":"agent_id must be a string","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"python/copilot/session.py","lineNumber":291,"sourceCode":"    \"\"\"MIME type of the inline data\"\"\"\n    displayName: NotRequired[str]\n\n\nAttachment = FileAttachment | DirectoryAttachment | SelectionAttachment | BlobAttachment\n\n\n@dataclass(frozen=True)\nclass AgentMessageSource:\n    \"\"\"Identify the agent that produced a message.\n\n    The agent ID is opaque and is sent unchanged after the ``agent-`` prefix.\n    \"\"\"\n\n    agent_id: str\n\n    def __post_init__(self) -> None:\n        if not isinstance(self.agent_id, str):\n            raise TypeError(\"agent_id must be a string\")\n\n\nMessageSource = Literal[\"user\", \"system\"] | AgentMessageSource\n\"\"\"Message provenance, independent of delivery mode.\"\"\"\n\n# ============================================================================\n# System Message Configuration\n# ============================================================================\n\n\nclass SystemMessageAppendConfig(TypedDict, total=False):\n    \"\"\"\n    Append mode: Use CLI foundation with optional appended content.\n    \"\"\"\n\n    mode: NotRequired[Literal[\"append\"]]\n    content: NotRequired[str]\n","sourceCodeStart":273,"sourceCodeEnd":309,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/python/copilot/session.py#L273-L309","documentation":"The message dataclass (a ChatMessage-like record with an `agent_id: str` field) validates its fields in __post_init__ and raises this TypeError when agent_id is not a str. Because Python dataclasses do not enforce annotations at runtime, the library performs this explicit check to keep agent identity a string throughout the session API.","triggerScenarios":"Constructing the message with agent_id as None, an int, an AgentId-like object, bytes, or a missing-then-defaulted value — e.g. `Message(agent_id=123, ...)` or passing an optional agent id that was None.","commonSituations":"Passing a typed ID wrapper object instead of str(agent_id); JSON payloads where agent_id was null; mixing agent IDs from an older API version where they were numeric.","solutions":["Convert the value to a string before construction: `Message(agent_id=str(agent_id), ...)`.","Ensure the source of agent_id actually supplies a non-None string; fix upstream parsing if it yields None.","If agent_id is genuinely optional in your flow, use a sentinel string or restructure rather than passing None."],"exampleFix":"// before\nmsg = Message(agent_id=agent.id, content=\"hi\")  # agent.id is int\n\n// after\nif not isinstance(agent.id, str):\n    raise ValueError(\"agent id must be a string\")\nmsg = Message(agent_id=str(agent.id), content=\"hi\")","handlingStrategy":"type-guard","validationCode":"if not isinstance(agent_id, str):\n    raise ValueError(f\"agent_id must be str, got {type(agent_id).__name__}\")","typeGuard":"def is_agent_id(value: object) -> TypeGuard[str]:\n    return isinstance(value, str) and len(value) > 0","tryCatchPattern":"try:\n    msg = Message(agent_id=agent_id, content=content)\nexcept TypeError as e:\n    if \"agent_id\" in str(e):\n        msg = Message(agent_id=str(agent_id), content=content)\n    else:\n        raise","preventionTips":["Coerce IDs to str at API boundaries with str(agent_id).","Reject None early if agent_id is mandatory in your flow.","Enable runtime type checking (e.g. beartype/typeguard) around message construction in tests."],"tags":["type-error","dataclass","validation","python"],"backgroundTag":"type-mismatch","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}