Registry¶
The Registry is Protolink's discovery service. Agents register their AgentCard with it, and other agents query it to find peers by name, role, tags, capabilities, or other card metadata.
Use a registry when agents should discover each other dynamically instead of hard-coding every peer URL.
Quick Start¶
from protolink.discovery import Registry
registry = Registry(url="http://localhost:9000", transport="http")
registry.start(background=True)
# ...start agents that use this registry...
registry.stop()
Agents can receive the live Registry object directly:
from protolink.agents import Agent
agent = Agent(
card=card,
transport="http",
registry=registry,
)
Or they can connect to a registry by transport type and URL:
from protolink.agents import Agent
agent = Agent(
card=card,
transport="http",
registry="http",
registry_url="http://localhost:9000",
registry_heartbeat_interval=15,
)
Filters are optional
Calling discover() with no filters returns all registered agents.
Discovery¶
cards = await registry.discover({"name": "weather_agent"})
cards = await registry.discover({"role": "worker"})
cards = await registry.discover({"tags": ["weather", "forecast"]})
Discovery returns AgentCard objects. The same filter shape is available through Agent.discover_agents() and RegistryClient.discover().
Transport Integration¶
The Registry is transport-agnostic. It relies on a Transport implementation to expose its API.
Currently supported by the default runtime path:
HTTPTransportviatransport="http"
The transport is responsible for:
- Binding to a host and port
- Exposing registry endpoints
- Handling request/response lifecycle
Lifecycle Methods¶
These methods control the registry server component lifecycle.
| Name | Parameters | Returns | Description |
|---|---|---|---|
start() |
background: bool = False |
None |
Starts the Registry runtime. Can run in the main loop or as an isolated background thread. |
stop() |
- | None |
Stops the Registry runtime and synchronously cleans up resources. |
Execution Models¶
background=Truestarts the registry in a dedicated background thread with its own isolatedasyncioevent loop and returns immediately. Use this for examples, notebooks, tests, and multi-agent scripts.background=Falseblocks the main thread until the registry is stopped. Use this for a standalone registry process.
Common Usage Patterns¶
Standalone registry service
from protolink.discovery import Registry
registry = Registry(url="http://localhost:9000", transport="http")
registry.start()
Multi-agent orchestration
registry.start(background=True)
agent.start(background=True)
# ...run your orchestration...
agent.stop()
registry.stop()
Graceful shutdown
Always use registry.stop() to cleanly shut down the server and release ports. In blocking scripts, registry.start(background=False) handles KeyboardInterrupt automatically.
Discovery Performance¶
The Registry is optimized for high-throughput environments where many agents may be registered simultaneously.
Secondary Indexing¶
To avoid linear scans during common discovery queries, the Registry maintains secondary indexes for:
- Agent name
- Agent role
- Tags
When multiple indexed filters are applied, the Registry performs set intersections and then refines matches for any non-indexed fields.
Robust Fallback¶
If a query uses non-indexed fields, or if the indexed path returns no candidates while agents are still present, the Registry falls back to a full scan to preserve correctness.
Liveness And Persistence¶
By default, the registry is an in-memory discovery service. For longer-running systems, two optional knobs make it more robust:
entry_ttl_secondsprunes agents whoselast_seentimestamp is older than the configured TTL.storagepersists registered entries through the genericStorageinterface, so a registry can rebuild its in-memory indexes after restart.
Agents can keep their entry fresh by setting registry_heartbeat_interval on the Agent. After successful registration, the agent periodically calls RegistryClient.heartbeat(agent_url). Heartbeats update liveness metadata only; they do not mutate the agent card or discovery indexes.
from protolink import Agent, AgentCard
from protolink.discovery import Registry
from protolink.storage import SQLiteStorage
registry = Registry(
url="http://localhost:9000",
transport="http",
entry_ttl_seconds=45,
storage=SQLiteStorage("registry.db", namespace="registry"),
)
agent = Agent(
AgentCard(name="worker", description="Worker", url="http://localhost:9010"),
transport="http",
registry="http",
registry_url="http://localhost:9000",
registry_heartbeat_interval=15,
)
The public registry API now includes:
| Method | Purpose |
|---|---|
register(card) |
Add or replace an agent card and update secondary indexes. |
heartbeat(agent_url) |
Refresh last_seen for a registered agent. |
unregister(agent_url) |
Remove an agent and its indexes. |
discover(filter_by=None) |
Return live agent cards, pruning expired entries first. |
Constructor¶
Registry(
transport: TransportType | Transport = "http",
url: str | None = None,
verbosity: Literal[0, 1, 2] = 1,
*,
entry_ttl_seconds: float | None = None,
storage: Storage | None = None,
)
| Parameter | Type | Default | Description |
|---|---|---|---|
transport |
TransportType | Transport |
"http" |
Transport instance or registered transport string. |
url |
str | None |
None |
Registry URL. Required when transport is a string. |
verbosity |
Literal[0, 1, 2] |
1 |
Logging verbosity: 0 = warning, 1 = info, 2 = debug. |
entry_ttl_seconds |
float | None |
None |
Optional liveness TTL. Expired entries are pruned before discovery, status, and count/list operations. |
storage |
Storage | None |
None |
Optional persistence for serialized registry entries. |
Single source of truth
The Registry's public URL is derived from its transport and used by agents for registration and discovery.
URL Handling¶
Both Agents and the Registry expose a url property through their transport.
from protolink.transport import HTTPTransport
transport = HTTPTransport(url="http://localhost:9000")
registry = Registry(transport=transport)
This keeps host, port, transport, and discovery metadata consistent across agent and registry instances.