Agent Zero Communication Protocol: How Agents Talk Across Process Boundaries
Agent Zero uses an HTTP-based Remote Function Call (RFC) protocol that encrypts payloads with a pre-shared secret and validates SHA-256 hashes to enable secure cross-process communication between agents.
Agent Zero is an open-source AI agent framework that enables distributed agent workflows across multiple processes or containers. The communication protocol between agents in Agent Zero relies on a custom Remote Function Call (RFC) implementation that bridges these boundaries through encrypted HTTP requests, ensuring that function calls between agents remain secure and tamper-proof.
How the Agent Zero RFC Protocol Works
The RFC protocol operates through a six-step request-response cycle that transforms local Python function calls into encrypted HTTP transactions.
Step 1: Building the RFC Request
When an agent needs to invoke a function in another process, it calls runtime.call_development_function. This helper extracts the target function's module path, name, and arguments, then encapsulates them in an RFCInput object.
# runtime.py – lines 95-113
async def call_development_function(func, *args, **kwargs):
# Extract module path and function name from the callable
rfc_input = RFCInput(
module=func.__module__,
name=func.__name__,
args=args,
kwargs=kwargs
)
return await _execute_rfc_call(rfc_input)
Step 2: Payload Encryption and Hashing
The RFCInput object is JSON-encoded and cryptographically signed. The system computes a SHA-256 hash of the JSON string combined with the RFC password using crypto.hash_data, then stores both the hash and the payload in an RFCCall dictionary.
# rfc.py – lines 31-39
def create_rfc_call(rfc_input: RFCInput, password: str) -> dict:
json_payload = json.dumps(rfc_input.to_dict())
signature = crypto.hash_data(json_payload + password)
return {
"payload": json_payload,
"hash": signature
}
Step 3: HTTP Transmission
The caller POSTs the RFCCall to the target agent's RFC endpoint. The URL is determined by _get_rfc_url(), which defaults to http://<host>:<port>/rfc. The _send_json_data helper handles the actual HTTP transmission.
# runtime.py – lines 99-104
url = _get_rfc_url(target_host, target_port)
rfc_call = create_rfc_call(rfc_input, _get_rfc_password())
# rfc.py – _send_json_data (lines 70-78)
async def _send_json_data(url: str, data: dict) -> dict:
async with aiohttp.ClientSession() as session:
async with session.post(url, json=data) as response:
return await response.json()
Step 4: Server-Side Verification
Upon receiving the request, the RFC server endpoint extracts the JSON payload and signature, then verifies the hash using the same pre-shared password via crypto.verify_data. If verification fails, the server raises a security exception and aborts processing.
# rfc.py – lines 44-47
def verify_rfc_call(rfc_call: dict, password: str) -> RFCInput:
payload = rfc_call["payload"]
signature = rfc_call["hash"]
if not crypto.verify_data(payload + password, signature):
raise SecurityError("RFC hash verification failed")
return RFCInput.from_json(payload)
Step 5: Dynamic Function Dispatch
After verification, the server parses the RFCInput to determine the target module and function. It uses importlib.import_module to dynamically import the specified module, then retrieves the function via getattr. If the function is a coroutine, it is awaited; otherwise, it is called synchronously.
# rfc.py – lines 48-60
async def dispatch_rfc_call(rfc_input: RFCInput):
module = importlib.import_module(rfc_input.module)
func = getattr(module, rfc_input.name)
if asyncio.iscoroutinefunction(func):
result = await func(*rfc_input.args, **rfc_input.kwargs)
else:
result = func(*rfc_input.args, **rfc_input.kwargs)
return result
Step 6: Returning the Result
The function's return value is serialized to JSON and sent back as the HTTP response body. The caller receives this JSON and deserializes it as the final result of call_development_function.
# runtime.py – lines 114-115
response_data = await _send_json_data(url, rfc_call)
return response_data["result"]
Security Architecture of the Communication Protocol
The Agent Zero communication protocol implements defense-in-depth through cryptographic validation and environment-based secret management.
Pre-Shared Key Authentication
The system requires the A0_RFC_PASSWORD environment variable (defined as dotenv.KEY_RFC_PASSWORD in the configuration). The runtime._get_rfc_password() function reads this value at startup, and if missing, aborts with an exception. This symmetric secret ensures only agents possessing the password can generate or verify valid RFC calls.
Integrity Verification via SHA-256
Every payload is concatenated with the password and hashed using crypto.hash_data. The receiving agent recomputes this hash using crypto.verify_data. This HMAC-like construction prevents tampering in transit, even if the underlying HTTP connection lacks TLS.
Development Mode Isolation
The runtime.is_development() check ensures RFC is only active in development environments. Production deployments bypass the HTTP layer and execute functions locally, eliminating network attack surfaces when cross-process communication is unnecessary.
Core Implementation Files
The RFC protocol is implemented across four primary files in the python/helpers/ directory:
| File | Responsibility |
|---|---|
python/helpers/rfc.py |
Core protocol implementation including RFCInput/RFCCall structures, crypto.hash_data integration, HTTP transport via _send_json_data, and dynamic dispatch through importlib. |
python/helpers/runtime.py |
High-level API exposing call_development_function and _get_rfc_url, orchestrating the conversion of Python callables into RFC requests. |
python/helpers/rfc_exchange.py |
Specialized helper for secure secret exchange, demonstrating how RFC can transport sensitive data like root passwords between privileged agents. |
python/helpers/crypto.py |
Cryptographic primitives providing hash_data, verify_data, and encryption routines used by the RFC layer for payload signing. |
Cross-Agent Function Call Example
The following example demonstrates how Agent A invokes a function residing in Agent B's process using the RFC protocol:
# Agent A (Caller) - initiates the remote call
from python.helpers import runtime
async def fetch_user_data(user_id: str):
# This function signature matches the remote implementation
async def _remote_impl(user_id):
pass # Placeholder; actual logic runs in Agent B
# runtime.call_development_function serializes the call and sends via HTTP RFC
result = await runtime.call_development_function(
_remote_impl,
user_id
)
return result
# Agent B (Target) - hosts the actual implementation
# File: agents/profile.py
async def get_user_profile(user_id: str) -> dict:
"""Executed locally in Agent B when invoked via RFC."""
return {
"id": user_id,
"name": "Jane Doe",
"status": "active"
}
When runtime.call_development_function executes, it automatically:
- Extracts the module path
agents.profileand function nameget_user_profilefrom the placeholder function's metadata - Constructs an
RFCInputobject and computes the SHA-256 hash using theA0_RFC_PASSWORDsecret - POSTs the encrypted payload to
http://<agent-b-host>:<port>/rfc - Agent B verifies the hash, imports
agents.profile, executesget_user_profile, and returns the JSON result
Summary
Agent Zero enables secure inter-agent communication through a custom HTTP-based Remote Function Call protocol that balances flexibility with cryptographic security:
- RFC Protocol: Agents communicate via HTTP POST requests to
/rfcendpoints, serializing function calls as JSON payloads wrapped inRFCCallstructures. - Cryptographic Validation: Every message includes a SHA-256 hash computed with the pre-shared
A0_RFC_PASSWORD, ensuring integrity and authentication viacrypto.hash_dataandcrypto.verify_data. - Dynamic Dispatch: The server uses
importlib.import_moduleandgetattrto dynamically locate and execute the target function, supporting both synchronous and asynchronous callables. - Development Isolation: The
runtime.is_development()check ensures RFC is only active in development environments, falling back to local execution in production.
Frequently Asked Questions
What protocol do Agent Zero agents use to communicate?
Agent Zero agents use an HTTP-based Remote Function Call (RFC) protocol implemented in python/helpers/rfc.py. This protocol allows one agent to invoke Python functions residing in another agent's process by serializing the function call as a JSON payload, cryptographically signing it with a pre-shared secret, and transmitting it via HTTP POST to the /rfc endpoint.
How does Agent Zero secure cross-process function calls?
Security is enforced through symmetric key authentication and hash verification. Before transmission, the caller concatenates the JSON payload with the A0_RFC_PASSWORD environment variable and computes a SHA-256 hash using crypto.hash_data. The receiver verifies this hash with crypto.verify_data using the same password. If verification fails, the request is rejected, preventing unauthorized agents from executing remote functions even if they can reach the HTTP endpoint.
What is the RFCInput object in Agent Zero?
RFCInput is a data structure defined in python/helpers/rfc.py that encapsulates the metadata required to invoke a remote function. It stores the module path (e.g., agents.profile), the function name, and the arguments (args and kwargs) to be passed. The runtime.call_development_function helper automatically constructs this object from the caller's function signature, which is then JSON-encoded and wrapped in an RFCCall dictionary for transmission.
Can Agent Zero RFC work over HTTPS?
Yes, while the default configuration uses HTTP to http://<host>:<port>/rfc, the protocol is transport-agnostic regarding encryption. You can configure the target URL to use HTTPS by modifying the return value of _get_rfc_url() in python/helpers/runtime.py or setting the appropriate host configuration. The cryptographic hash verification provides an additional layer of security independent of transport encryption, ensuring payload integrity even if TLS is not configured.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →