From e0e99a104806d50353905d7b246b1a1c1882eb21 Mon Sep 17 00:00:00 2001 From: peterychang <49209570+peterychang@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:45:38 -0400 Subject: [PATCH] Standardize Agent and Topic ID strings + documentation (#638) * Standardize Agent and Topic ID strings + documentation * Add specs --------- Co-authored-by: Jack Gerrits --- docs/design/04 - Agent and Topic ID Specs.md | 47 +++++++++++++++++++ .../agent-identity-and-lifecycle.md | 5 ++ .../core-concepts/topic-and-subscription.md | 7 +++ .../src/autogen_core/base/_agent_id.py | 4 +- .../src/autogen_core/base/_topic.py | 13 +++++ 5 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 docs/design/04 - Agent and Topic ID Specs.md diff --git a/docs/design/04 - Agent and Topic ID Specs.md b/docs/design/04 - Agent and Topic ID Specs.md new file mode 100644 index 0000000000..22a8a08894 --- /dev/null +++ b/docs/design/04 - Agent and Topic ID Specs.md @@ -0,0 +1,47 @@ +# Agent and Topic ID Specs + +This document describes the structure, constraints, and behavior of Agent IDs and Topic IDs. + +## Agent ID + +### Required Attributes + +#### type + +* Type: `string` +* Description: The agent type is not an agent class. It associates an agent with a specific factory function, which produces instances of agents of the same agent `type`. For example, different factory functions can produce the same agent class but with different constructor perameters. +* Constraints: UTF8 and only contain alphanumeric letters (a-z) and (0-9), or underscores (_). A valid identifier cannot start with a number, or contain any spaces. +* Examples: + * `code_reviewer` + * `WebSurfer` + * `UserProxy` + +#### key + +* Type: `string` +* Description: The agent key is an instance identifier for the given agent `type` +* Constraints: UTF8 and only contain characters between (inclusive) ascii 32 (space) and 126 (~). +* Examples: + * `default` + * A memory address + * a UUID string + +## Topic ID + +### Required Attributes + +#### type + +* Type: `string` +* Description: topic type is usually defined by application code to mark the type of messages the topic is for. +* Constraints: UTF8 and only contain alphanumeric letters (a-z) and (0-9), or underscores (_). A valid identifier cannot start with a number, or contain any spaces. +* Examples: + * `GitHub_Issues` + +#### source + +* Type: `string` +* Description: Topic source is the unique identifier for a topic within a topic type. It is typically defined by application data. +* Constraints: UTF8 and only contain characters between (inclusive) ascii 32 (space) and 126 (~). +* Examples: + * `github.com/{repo_name}/issues/{issue_number}` \ No newline at end of file diff --git a/python/packages/autogen-core/docs/src/core-user-guide/core-concepts/agent-identity-and-lifecycle.md b/python/packages/autogen-core/docs/src/core-user-guide/core-concepts/agent-identity-and-lifecycle.md index fffa934ed5..31225585f6 100644 --- a/python/packages/autogen-core/docs/src/core-user-guide/core-concepts/agent-identity-and-lifecycle.md +++ b/python/packages/autogen-core/docs/src/core-user-guide/core-concepts/agent-identity-and-lifecycle.md @@ -27,6 +27,11 @@ For example, different factory functions can produce the same agent class but with different constructor perameters. The agent key is an instance identifier for the given agent type. +Agent IDs can be converted to and from strings. the format of this string is: +```{note} +Agent_Type/Agent_Key +``` +Types and Keys are considered valid if they only contain alphanumeric letters (a-z) and (0-9), or underscores (_). A valid identifier cannot start with a number, or contain any spaces. In a multi-agent application, agent types are typically defined directly by the application, i.e., they diff --git a/python/packages/autogen-core/docs/src/core-user-guide/core-concepts/topic-and-subscription.md b/python/packages/autogen-core/docs/src/core-user-guide/core-concepts/topic-and-subscription.md index 885dc18f81..1c93bfd928 100644 --- a/python/packages/autogen-core/docs/src/core-user-guide/core-concepts/topic-and-subscription.md +++ b/python/packages/autogen-core/docs/src/core-user-guide/core-concepts/topic-and-subscription.md @@ -38,6 +38,13 @@ as the topic source to uniquely identifies the topic. Topic source allows the publisher to limit the scope of messages and create silos. +Topic IDs can be converted to and from strings. the format of this string is: +```{note} +Topic_Type/Topic_Source +``` +Types are considered valid if they are in UTF8 and only contain alphanumeric letters (a-z) and (0-9), or underscores (_). A valid identifier cannot start with a number, or contain any spaces. +Sources are considered valid if they are in UTF8 and only contain characters between (inclusive) ascii 32 (space) and 126 (~). + ## Subscription A subscription maps topic to agent IDs. diff --git a/python/packages/autogen-core/src/autogen_core/base/_agent_id.py b/python/packages/autogen-core/src/autogen_core/base/_agent_id.py index 1459f250f5..06f163ed9c 100644 --- a/python/packages/autogen-core/src/autogen_core/base/_agent_id.py +++ b/python/packages/autogen-core/src/autogen_core/base/_agent_id.py @@ -18,7 +18,7 @@ class AgentId: return hash((self._type, self._key)) def __str__(self) -> str: - return f"{self._type}:{self._key}" + return f"{self._type}/{self._key}" def __repr__(self) -> str: return f'AgentId(type="{self._type}", key="{self._key}")' @@ -30,7 +30,7 @@ class AgentId: @classmethod def from_str(cls, agent_id: str) -> Self: - items = agent_id.split(":", maxsplit=1) + items = agent_id.split("/", maxsplit=1) if len(items) != 2: raise ValueError(f"Invalid agent id: {agent_id}") type, key = items[0], items[1] diff --git a/python/packages/autogen-core/src/autogen_core/base/_topic.py b/python/packages/autogen-core/src/autogen_core/base/_topic.py index f693a3eb44..80c29d95f1 100644 --- a/python/packages/autogen-core/src/autogen_core/base/_topic.py +++ b/python/packages/autogen-core/src/autogen_core/base/_topic.py @@ -1,5 +1,7 @@ from dataclasses import dataclass +from typing_extensions import Self + @dataclass(eq=True, frozen=True) class TopicId: @@ -14,3 +16,14 @@ class TopicId: Learn more here: https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#source-1 """ + + def __str__(self) -> str: + return f"{self.type}/{self.source}" + + @classmethod + def from_str(cls, topic_id: str) -> Self: + items = topic_id.split("/", maxsplit=1) + if len(items) != 2: + raise ValueError(f"Invalid topic id: {topic_id}") + type, source = items[0], items[1] + return cls(type, source)