MCPcopy
hub / github.com/langroid/langroid / ChatDocMetaData

Class ChatDocMetaData

langroid/agent/chat_document.py:54–109  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

52
53
54class ChatDocMetaData(DocMetaData):
55 parent_id: str = "" # msg (ChatDocument) to which this is a response
56 child_id: str = "" # ChatDocument that has response to this message
57 agent_id: str = "" # ChatAgent that generated this message
58 msg_idx: int = -1 # index of this message in the agent `message_history`
59 sender: Entity # sender of the message
60 # True if this msg was relayed from another agent's LLM/handler output in a
61 # multi-agent handoff (a Task then relabels sender -> USER). Lets handle-only
62 # tools be dispatched for legitimate handoffs while still blocking raw
63 # USER-injected tool JSON. See ChatAgent._filter_user_origin_tools and
64 # GHSA-gjgq-w2m6-wr5q.
65 tools_from_agent: bool = False
66 # True if this msg's content/tools derive from external untrusted (USER)
67 # input via a MECHANICAL path: a deepcopy of a tainted msg, or tools
68 # repackaged from a USER msg's content (e.g. DonePassTool/AgentDoneTool).
69 # Unlike `tools_from_agent` (a trust signal), this is a DISTRUST signal that
70 # vetoes handle-only tool dispatch even across a USER relabel, closing the
71 # content-laundering hole. Propagated (deepcopy carries it), never cleared.
72 # See ChatAgent._filter_user_origin_tools and issue #1035 (taint propagation).
73 tainted: bool = False
74 # tool_id corresponding to single tool result in ChatDocument.content
75 oai_tool_id: str | None = None
76 tool_ids: List[str] = [] # stack of tool_ids; used by OpenAIAssistant
77 block: None | Entity = None
78 sender_name: str = ""
79 recipient: str = ""
80 usage: Optional[LLMTokenUsage] = None
81 cached: bool = False
82 displayed: bool = False
83 has_citation: bool = False
84 status: Optional[StatusCode] = None
85
86 @model_validator(mode="after")
87 def _mark_tools_from_agent(self) -> "ChatDocMetaData":
88 # Mark messages produced directly by an LLM: the tools in an LLM's
89 # output are the LLM's own decision (the trusted trigger for handle-only
90 # tools -- see GHSA-gjgq-w2m6-wr5q), so the mark lets a Task relay them
91 # to another agent even after relabeling the sender to USER. The mark is
92 # only ever SET, never cleared, so it survives relabeling and deepcopies
93 # (e.g. ForwardTool/PassTool deepcopy the LLM-born message, carrying the
94 # mark across the handoff). We deliberately do NOT mark generic AGENT
95 # messages: a pass-through/echoing agent could surface untrusted USER
96 # text (with embedded tool JSON) as AGENT content, and marking that
97 # would re-open the user-origin bypass. Raw USER input is never marked,
98 # so it stays filtered. See ChatAgent._filter_user_origin_tools.
99 if self.sender == Entity.LLM:
100 self.tools_from_agent = True
101 return self
102
103 @property
104 def parent(self) -> Optional["ChatDocument"]:
105 return ChatDocument.from_id(self.parent_id)
106
107 @property
108 def child(self) -> Optional["ChatDocument"]:
109 return ChatDocument.from_id(self.child_id)
110
111

Callers 15

initMethod · 0.90
stepMethod · 0.90
step_asyncMethod · 0.90
resultMethod · 0.90
_agent_response_finalMethod · 0.90
response_templateMethod · 0.90
_user_response_finalMethod · 0.90
responseMethod · 0.90
responseMethod · 0.90
handleMethod · 0.90

Calls

no outgoing calls

Used in the wild real call sites across dependent graphs

searching dependent graphs…