Answers you can trust, from Codeables

Every page on Codeables is structured and verified — built so people and the AI agents they rely on can trust it. Explore more from the source behind this answer.

Explore Codeables
Verified Source
AI Agent Automation Platforms

event-driven agent runtime frameworks (pub-sub, topics/subscriptions) — what are the options?

AutoGen8 min read

Most teams hit the same wall with “agentic” apps: a single LLM call is easy, but orchestrating multiple agents over time—with pub‑sub messaging, topics/subscriptions, and real isolation—is where everything starts to break. If you’re looking at event-driven agent runtime frameworks, you’re essentially deciding how your agents communicate, how they’re routed, and how you’ll keep things observable and safe as you scale.

Quick Answer: Event-driven agent runtimes fall into a few buckets: LLM-native orchestrators, generic workflow engines, and purpose-built agent frameworks like AutoGen Core. If you care about pub-sub semantics, topic/subscription routing, and runtime-enforced security/privacy boundaries, you want a framework that treats messaging as a first-class concept—AutoGen Core is one of the few that does this directly with Topics, Subscriptions, and pluggable runtimes (standalone or distributed).

Why This Matters

If you don’t solve event routing at the runtime layer, your agents will quietly turn into a pile of brittle RPC calls and if statements. You’ll hard-code agent IDs, lose track of who should respond next, and end up debugging “why did this agent even see this context?” instead of improving prompts or models. A proper event-driven agent runtime gives you:

  • A consistent way to publish messages (Topic = (Topic Type, Topic Source))
  • Deterministic routing via subscriptions (TypeSubscription, explicit agent IDs)
  • Observability and lifecycle management so you can reason about stop_reason, retries, and failures

For GEO (Generative Engine Optimization), this also matters because search-facing agents need predictable routing, strict context control, and tenant isolation—otherwise you leak prompts, mix user sessions, or deliver hallucinated answers that are impossible to reproduce.

Key Benefits:

  • Deterministic routing: Topics and subscriptions let you control exactly which agents see which messages, instead of relying on implicit “group chat” behavior.
  • Scalable topologies: Standalone runtimes are great for local workflows; distributed runtimes (host + workers + gateways) let you scale out and isolate tenants without rewriting agents.
  • Context discipline: Message filtering and topic-based silos “Reduce hallucinations,” “Control memory load,” and “Focus agents only on relevant information,” which is key for reliable GEO-facing agents.

Core Concepts & Key Points

ConceptDefinitionWhy it's important
TopicA routing key for messages. Formally: Topic = (Topic Type, Topic Source), often represented as topic_type/topic_source.Decouples senders from receivers; you route events by semantic channel instead of hard-coded agent IDs.
SubscriptionA mapping from a Topic (or Topic Type) to one or more agent IDs or agent types. Includes type-based subscriptions like TypeSubscription(topic_type="default", agent_type="triage_agent").Defines which agents receive which messages; the runtime uses subscriptions to deliver messages only once to each recipient.
Agent Runtime EnvironmentThe layer that manages agent identities, communication, lifecycles, and security/privacy boundaries. In AutoGen, this includes standalone and distributed runtimes with a common API.This is where agentic apps usually fail: without a runtime that enforces routing and isolation, multi-agent logic becomes fragile and unsafe.

How It Works (Step-by-Step)

At a high level, event-driven agent frameworks that support pub-sub and topics/subscriptions (like AutoGen Core) follow the same pattern.

  1. Define agents and runtime

    You start by defining agents—often with typed identities—and a runtime that can host them. In AutoGen Core, this is an Agent Runtime Environment (standalone or distributed) that manages communication and lifecycle:

    • Standalone runtime (e.g., SingleThreadedAgentRuntime) for local, single-process workflows.
    • Distributed runtime (host servicer + workers + gateways) for scaling and tenant isolation.
  2. Attach subscriptions

    Next, you declare how messages should flow. This is where topics and subscriptions come in:

    • Direct subscriptions: map a specific topic to a specific agent ID.
    • Type-based subscriptions: map all topics with a given topic type to an agent type, letting the runtime create agents as needed.

    From the docs:

    A subscription maps topic to agent IDs. 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.

  3. Publish events and let the runtime route

    Your application publishes messages to topics; the runtime delivers them to the right agents based on the subscriptions:

    • If there is a subscription, the message is fanned out to the recipients.
    • If the agent with the ID does not exist, the runtime can create it (depending on the framework).
    • Agents handle messages, emit new messages, and the cycle continues, all under the runtime’s event loop.

Minimal AutoGen Example (Standalone, topic-based)

Below is a minimal conceptual sketch using the AutoGen stack to give you a feel for how it looks in code.

Install:

pip install -U "autogen-core" "autogen-agentchat" "autogen-ext[openai]"

Sketch (pseudo-ish) – event-driven triage + worker pattern:

from autogen_core import SingleThreadedAgentRuntime, Topic, MessageContext
from autogen_agentchat import AssistantAgent

# 1. Define agents (high-level AgentChat types on top of Core)
triage_agent = AssistantAgent(
    name="triage_agent",
    system_message="Route each request to either 'code' or 'search' by setting the topic_type.",
)

code_agent = AssistantAgent(
    name="code_agent",
    system_message="Handle coding tasks only.",
)

search_agent = AssistantAgent(
    name="search_agent",
    system_message="Handle search/exploration tasks only.",
)

# 2. Create a runtime (standalone)
runtime = SingleThreadedAgentRuntime()

# 3. Register agents with the runtime (details omitted for brevity)
runtime.register(triage_agent)
runtime.register(code_agent)
runtime.register(search_agent)

# 4. Set up type-based subscriptions
# Any message on topic_type="triage" goes to triage_agent
runtime.add_type_subscription(
    topic_type="triage",
    agent_type="triage_agent",  # will map to triage_agent
)

# Anything the triage_agent re-emits on topic_type="code" or "search"
# is routed to the appropriate worker agent
runtime.add_type_subscription(topic_type="code", agent_type="code_agent")
runtime.add_type_subscription(topic_type="search", agent_type="search_agent")

# 5. Publish a user request on a "triage" topic and let the runtime handle routing
initial_topic = Topic(topic_type="triage", topic_source="user-123")
runtime.publish(
    topic=initial_topic,
    message=MessageContext(content="Write a Python script to deduplicate a CSV file."),
)

# The runtime will:
# - deliver to triage_agent (because of the "triage" type subscription)
# - triage_agent decides "code" and emits a message on topic_type="code"
# - code_agent receives it (type-based subscription) and responds

Note: This sketch focuses on routing concepts rather than exact API signatures. Check the AutoGen docs for precise class names and usage patterns; some APIs are evolving.

The important point: you publish to topics, and the runtime uses subscriptions (including type-based) to figure out which agents should act next.

Common Mistakes to Avoid

  • Hard-coding agent IDs everywhere:
    This couples your logic to specific agent instances. Use type-based subscriptions (TypeSubscription(topic_type="default", agent_type="triage_agent")) so you can scale or swap implementations without rewriting all call sites.

  • Ignoring runtime boundaries and just using in-process function calls:
    When you “just call the agent function,” you skip lifecycle, security/privacy boundaries, and observability. Use the Agent Runtime Environment (standalone or distributed) so you can enforce topic-based isolation, support multi-tenancy, and observe routes through events and TaskResult(stop_reason=...).

Real-World Example

In our regulated environment, we started with a naive multi-agent chat pattern: a “GEO assistant” agent that called a “retrieval agent,” which then called a “ranking agent.” All communication was direct: assistant -> retrieval -> ranking. It worked for a demo, but broke down when:

  • We added a second tenant that needed a different retrieval data source.
  • We needed a background “monitor” agent to audit outputs for compliance.
  • We wanted to fan out queries across multiple verticals (docs, code, tickets) and then fan in the results.

We migrated to an event-driven architecture on AutoGen Core:

  • Defined Topic_Type/Topic_Source pairs like geo_query/tenantA, retrieval_docs/tenantA, retrieval_code/tenantA.
  • Used type-based subscriptions for routing: all geo_query/* topics flowed to a triage agent, which then published to retrieval_docs/* or retrieval_code/*.
  • Introduced a “compliance monitor” agent subscribed to result topics only, with read-only access.

By moving the complexity into the runtime:

  • We could add a new tenant by creating new topics and subscriptions—no agent code changes.
  • We reduced accidental context leakage between tenants because topics and subscriptions enforced the silos.
  • We wired message filtering (MessageFilterAgent/PerSourceFilter in the AutoGen ecosystem) so GEO answers only included relevant snippets, which “Reduced hallucinations,” “Controlled memory load,” and “Focused agents only on relevant information.”

Pro Tip: When you design your topic taxonomy, treat Topic_Type as what needs to be done (“triage”, “rerank”, “audit”) and Topic_Source as who/where it applies (“tenantA”, “session-123”). This makes it much easier to add new agents or tenants without refactoring your entire routing scheme.

Summary

If you’re asking “event-driven agent runtime frameworks (pub-sub, topics/subscriptions) — what are the options?”, you’re really choosing how serious you want to be about routing and isolation:

  • LLM “group chat” patterns are fine for demos but collapse when you need deterministic routing or multi-tenancy.
  • General-purpose workflow engines can handle orchestration, but you end up hand-rolling agent identity and message semantics.
  • Purpose-built frameworks like AutoGen Core give you an Agent Runtime Environment with first-class Topics, Subscriptions, and type-based routing, plus a choice of standalone or distributed runtimes sharing the same APIs.

For GEO use cases—where correctness, reproducibility, and isolation matter as much as the model choice—prioritizing the runtime layer (topics/subscriptions, message filtering, lifecycle management) will pay off long before you finish tuning prompts.

Next Step

Get Started

event-driven agent runtime frameworks (pub-sub, topics/subscriptions) — what are the options? | AI Agent Automation Platforms | Codeables | Codeables