camel
camel copied to clipboard
[Feature Request] `Message` refactor
Required prerequisites
- [X] I have searched the Issue Tracker and Discussions that this hasn't already been reported. (+1 or comment there if it has.)
- [ ] Consider asking first in a Discussion.
Motivation
learn from standards like FIPA and XMPP, refactor Message
to make it more scalable to multi-agent communication
Solution
Requirements on agents:
Agents should send not-understood if they receive a message that they do not recognise or they are unable to process the content of the message. Agents must be prepared to receive and properly handle a not-understood message from other agents.
message
attributes:
-
:message-id
unique id for this message
-
:type
type of the message
-
:sender
Denotes the identity of the sender of the message, i.e. the name of the agent of the communicative act.
{role_name, role_type}
-
:receiver
Denotes the identity of the intended recipient of the mess age. Note that the recipient may be a single agent name, or a tuple of agent names. This corresponds to the action of multicasting the message. Pragmatically, the semantics of this multicast is that the message is sent to each agent named in the tuple, and that the sender intends each of them to be recipient of the CA encoded in the message. For example, if an agent performs an inform act with a tuple of three agents as receiver, it denotes that the sender intends each of these agent to come to believe the content of the message.
-
:subject
The subject of this message
-
:content
Denotes the content of the message; equivalently denotes the object of the action.
{text, image, audio, video, tool_calling(tools, args, results)}
msg1 “content”, msg2 “content”
Multipurpose Internet Mail Extensions (MIME)
-
:reply-with
Introduces an expression which will be used by the agent responding to this message to identify the original message. Can be used to follow a conversation thread in a situation where multiple dialogues occur simultaneously.
E.g. if agent i sends to agent j a message which contains
:reply-with query1, agent j will respond with a message containing
:in-reply-to query1.
-
:in-reply-to
[message1,message2] → memory
Denotes an expression that references an earlier action to which this message is a reply.
-
:envelope
{time sent:xx, time received:xx}
Denotes an expression that provides useful information about the message as seen by the message transport service. The content of this parameter is not defined in the specification, but may include time sent, time received, route, etc. The structure of the envelope is a list of keyword value pairs, each of which denotes some aspect of the message service.
-
:language
Denotes the encoding scheme of the content of the action.
-
:ontology
Denotes the ontology which is used to give a meaning to the symbols in the content expression.
-
~~:reply-by~~
~~Denotes a time and/or date expression which indicates a guideline on the latest time by which the sending agent would like a reply.~~
-
:protocol
{schema: Multipurpose Internet Mail Extensions (MIME)}
Introduces an identifier which denotes the protocol which the sending agent is employing. The protocol serves to give additional context for the interpretation of the message.
-
:conversation-id / thread-id
uuid
Introduces an expression which is used to identify an ongoing sequence of communicative acts which together form a conversation. A conversation may be used by an agent to manage its communication strategies and activities. In addition the conversation may provide additional context for the interpretation of the meaning of a message.
message
types:
Information passing
- confirm
- disconfirm
- failure inform
- inform-if (macro act)
- inform-ref (macro act)
Requesting information
- query-if (could be
Task
with attributedescription
,expected_output
,structured output schema
,tools
specified to use,) - query-ref refuse
- subscribe
Negotiation
- accept-proposal
- cfp
- propose
- reject-proposal
Action performing
- agree
- cancel
- query-ref refuse
- request
- request-when
- request-whenever
Error handling
- failure inform
- not-understood
Structured Output:
output_file: File path for storing messag output.
output_json: Pydantic model for structuring JSON output.
output_pydantic: Pydantic model for task output.
https://github.com/outlines-dev/outlines
https://github.com/jxnl/instructor
https://github.com/argilla-io/distilabel
Message
Storage:
SQLLite
MySQL
PostgreSQL https://www.postgresql.org/
PostgreSQL supports complex data types such as JSON and JSONB, which can be useful for storing the structured message content with varied data types (text, image, audio, video, function_calling, etc.). It’s also highly extensible, allowing you to define custom functions, data types, and operators that can be very useful for your specific use case.
Example Schema Design in PostgreSQL:
CREATE TABLE agents (
agent_id SERIAL PRIMARY KEY,
role_name VARCHAR(255),
role_type VARCHAR(255)
);
CREATE TABLE messages (
message_id UUID PRIMARY KEY,
sender_id INTEGER REFERENCES agents(agent_id),
receiver_ids INTEGER[] REFERENCES agents(agent_id),
content JSONB,
reply_with UUID[],
in_reply_to UUID[],
envelope JSONB,
language VARCHAR(255),
ontology VARCHAR(255),
reply_by TIMESTAMP,
protocol JSONB,
conversation_id UUID
);
Draft implementation for Message
class:
from dataclasses import dataclass, field
from typing import Any, Dict, List, Tuple, Union
import uuid
@data. class
class Message:
message_id: str = field(default_factory=lambda: str(uuid.uuid4()))
type: str
sender: Tuple[str, str] # (role_name, role_type)
receiver: Union[str, Tuple[str, ...]] # Single agent or tuple of agents
subject: str
content: Any # Could be text, image, audio, video, function_calling
reply_with: List[str] = field(default_factory=list)
in_reply_to: List[str] = field(default_factory=list)
envelope: Dict[str, Any] = field(default_factory=dict)
language: str
ontology: str
reply_by: str # Time/date expression
protocol: Dict[str, str] = field(default_factory=lambda: {"schema": "MIME"})
conversation_id: str = field(default_factory=lambda: str(uuid.uuid4()))
structured_output: Any = None # Placeholder for structured output models
Discussion:
also add verbose?
unify current CAMEL message and response into 1?
Alternatives
No response
Additional context
No response