# Topic and Subscription There are two ways for runtime to deliver messages, direct messaging or broadcast. Direct messaging is one to one: the sender must provide the recipient's agent ID. On the other hand, broadcast is one to many and the sender does not provide recpients' agent IDs. Many scenarios are suitable for broadcast. For example, in event-driven workflows, agents do not always know who will handle their messages, and a workflow can be composed of agents with no inter-dependencies. This section focuses on the core concepts in broadcast: topic and subscription. ## Topic A topic defines the scope of a broadcast message. In essence, agent runtime implements a publish-subscribe model through its broadcast API: when publishing a message, the topic must be specified. It is an indirection over agent IDs. A topic consists of two components: topic type and topic source. ```{note} Topic = (Topic Type, Topic Source) ``` Similar to [agent ID](./agent-identity-and-lifecycle.md#agent-id), which also has two components, topic type is usually defined by application code to mark the type of messages the topic is for. For example, a GitHub agent may use `"GitHub_Issues"` as the topic type when publishing messages about new issues. Topic source is the unique identifier for a topic within a topic type. It is typically defined by application data. For example, the GitHub agent may use `"github.com/{repo_name}/issues/{issue_number}"` 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. ![Subscription](subscription.svg) The diagram above shows the relationship between topic and subscription. An agent runtime keeps track of the subscriptions and uses them to deliver messages to agents. If a topic has no subscription, messages published to this topic will not be delivered to any agent. If a topic has many subscriptions, messages will be delivered following all the subscriptions to every recipient agent only once. Applications can add or remove subscriptions using agent runtime's API. ## Type-based Subscription A type-based subscription maps a topic type to an agent type (see [agent ID](./agent-identity-and-lifecycle.md#agent-id)). It declares an unbounded mapping from topics to agent IDs without knowing the exact topic sources and agent keys. The mechanism is simple: any topic matching the type-based subscription's topic type will be mapped to an agent ID with the subscription's agent type and the agent key assigned to the value of the topic source. For Python API, use {py:class}`~autogen_core.components.TypeSubscription`. ```{note} Type-Based Subscription = Topic Type --> Agent Type ``` Generally speaking, type-based subscription is the preferred way to declare subscriptions. It is portable and data-independent: developers do not need to write application code that depends on specific agent IDs. ### Scenarios of Type-Based Subscription Type-based subscriptions can be applied to many scenarios when the exact topic or agent IDs are data-dependent. The scenarios can be broken down by two considerations: (1) whether it is single-tenant or multi-tenant, and (2) whether it is a single topic or multiple topics per tenant. A tenant typically refers to a set of agents that handle a specific user session or a specific request. #### Single-Tenant, Single Topic In this scenario, there is only one tenant and one topic for the entire application. It is the simplest scenario and can be used in many cases like a command line tool or a single-user application. To apply type-based subscription for this scenario, create one type-based subscription for each agent type, and use the same topic type for all the type-based subscriptions. When you publish, always use the same topic, i.e., the same topic type and topic source. For example, assuming there are three agent types: `"triage_agent"`, `"coder_agent"` and `"reviewer_agent"`, and the topic type is `"default"`, create the following type-based subscriptions: ```python # Type-based Subscriptions for single-tenant, single topic scenario TypeSubscription(topic_type="default", agent_type="triage_agent") TypeSubscription(topic_type="default", agent_type="coder_agent") TypeSubscription(topic_type="default", agent_type="reviewer_agent") ``` With the above type-based subscriptions, use the same topic source `"default"` for all messages. So the topic is always `("default", "default")`. A message published to this topic will be delivered to all the agents of all above types. Specifically, the message will be sent to the following agent IDs: ```python # The agent IDs created based on the topic source AgentID("triage_agent", "default") AgentID("coder_agent", "default") AgentID("reviewer_agent", "default") ``` The following figure shows how type-based subscription works in this example. ![Type-Based Subscription Single-Tenant, Single Topic Scenario Example](type-subscription-single-tenant-single-topic.svg) If the agent with the ID does not exist, the runtime will create it. #### Single-Tenant, Multiple Topics In this scenario, there is only one tenant but you want to control which agent handles which topic. This is useful when you want to create silos and have different agents specialized in handling different topics. To apply type-based subscription for this scenario, create one type-based subscription for each agent type but with different topic types. You can map the same topic type to multiple agent types if you want these agent types to share a same topic. For topic source, still use the same value for all messages when you publish. Continuing the example above with same agent types, create the following type-based subscriptions: ```python # Type-based Subscriptions for single-tenant, multiple topics scenario TypeSubscription(topic_type="triage", agent_type="triage_agent") TypeSubscription(topic_type="coding", agent_type="coder_agent") TypeSubscription(topic_type="coding", agent_type="reviewer_agent") ``` With the above type-based subscriptions, any message published to the topic `("triage", "default")` will be delivered to the agent with type `"triage_agent"`, and any message published to the topic `("coding", "default")` will be delivered to the agents with types `"coder_agent"` and `"reviewer_agent"`. The following figure shows how type-based subscription works in this example. ![Type-Based Subscription Single-Tenant, Multiple Topics Scenario Example](type-subscription-single-tenant-multiple-topics.svg) #### Multi-Tenant Scenarios In single-tenant scenarios, the topic source is always the same (e.g., `"default"`) -- it is hard-coded in the application code. When moving to multi-tenant scenarios, the topic source becomes data-dependent. ```{note} A good indication that you are in a multi-tenant scenario is that you need multiple instances of the same agent type. For example, you may want to have different agent instances to handle different user sessions to keep private data isolated, or, you may want to distribute a heavy workload across multiple instances of the same agent type and have them work on it concurrently. ``` Continuing the example above, if you want to have dedicated instances of agents to handle a specific GitHub issue, you need to set the topic source to be a unique identifier for the issue. For example, let's say there is one type-based subscription for the agent type `"triage_agent"`: ```python TypeSubscription(topic_type="github_issues", agent_type="triage_agent") ``` When a message is published to the topic `("github_issues", "github.com/microsoft/autogen/issues/1")`, the runtime will deliver the message to the agent with ID `("triage_agent", "github.com/microsoft/autogen/issues/1")`. When a message is published to the topic `("github_issues", "github.com/microsoft/autogen/issues/9")`, the runtime will deliver the message to the agent with ID `("triage_agent", "github.com/microsoft/autogen/issues/9")`. The following figure shows how type-based subscription works in this example. ![Type-Based Subscription Multi-Tenant Scenario Example](type-subscription-multi-tenant.svg) Note the agent ID is data-dependent, and the runtime will create a new instance of the agent if it does not exist. To support multiple topics per tenant, you can use different topic types, just like the single-tenant, multiple topics scenario.