Skip to content

Signal System

LLMling-agent uses signals to enable observation and reaction to various events throughout the system. These signals are particularly useful for building UIs, monitoring agent behavior, and implementing custom event handling.

Registry Events

Several components provide a standard set of signals for monitoring changes to their collections. These signals are accessible through the events property:

# Available on any BaseRegistry
events.adding = Signal(object)                    # (key, ) - Before addition
events.added = Signal(object, object)             # (key, value) - After addition
events.changing = Signal(object)                  # (key, ) - Before change
events.changed = Signal(object, object, object)   # (key, old_value, value) - After change
events.removing = Signal(object)                  # (key, ) - Before removal
events.removed = Signal(object, object)           # (key, value) - After removal

Components using BaseRegistry

AgentPool

Monitors agent additions and removals:

def on_agent_added(name: str, agent: Agent):
    print(f"New agent {name} added to pool")

pool.events.added.connect(on_agent_added)

ToolManager

Tracks tool registration and modifications:

def on_tool_changed(name: str, old_info: ToolInfo, new_info: ToolInfo):
    print(f"Tool {name} configuration changed")

agent.tools.events.changed.connect(on_tool_changed)

Agent Signals

The main Agent class provides signals for monitoring core agent activities:

message_received = Signal(ChatMessage[str])  # New message received
message_sent = Signal(ChatMessage)           # Agent sent a message
tool_used = Signal(ToolCallInfo)            # Tool was called
chunk_streamed = Signal(str, str)           # Streaming chunk was emitted (chunk, message_id)
run_failed = Signal(str, Exception)         # Run operation failed
agent_reset = Signal(AgentReset)            # Agent state was reset

Provider Signals

Base provider signals:

tool_used = Signal(ToolCallInfo)        # Tool execution
chunk_streamed = Signal(str, str)       # Streaming response chunk
model_changed = Signal(object)          # Model was changed

Conversation Manager Signals

Signals for conversation state changes:

history_cleared = Signal(HistoryCleared)  # Chat history was cleared

Talk/Connection Signals

Signals for agent communication:

message_received = Signal(ChatMessage)   # Original message
message_forwarded = Signal(ChatMessage)  # After transformation
node_connected = Signal(object)         # Message connection established
connection_added = Signal(Talk)          # New connection created

Common Use Cases

Building UIs

class ConsoleUI:
    def __init__(self, agent: Agent):
        # Core agent activity
        agent.message_sent.connect(self.display_message)
        agent.tool_used.connect(self.display_tool_usage)
        agent.chunk_streamed.connect(self.display_chunk)

        # Tool management
        agent.tools.events.added.connect(self.update_tool_display)
        agent.tools.events.changed.connect(self.refresh_tool_status)

Monitoring and Logging

def setup_monitoring(pool: AgentPool):
    # Monitor agent lifecycle
    pool.events.added.connect(lambda name, agent: logger.info("Agent added: %s", name))
    pool.events.removed.connect(lambda name, agent: logger.info("Agent removed: %s", name))

    # Monitor tool usage across all agents
    for agent in pool.values():
        agent.tool_used.connect(lambda tool: logger.info("Tool used: %s", tool.name))

Provider Model Changes

def on_model_change(new_model):
    # Update provider-specific settings for new model
    update_configuration(new_model)

provider.model_changed.connect(on_model_change)