# Agent Zero Communication Protocol: How Agents Talk Across Process Boundaries

> Discover the Agent Zero Communication Protocol. Learn how agents use an encrypted HTTP-based RFC for secure cross-process communication. Understand the technology behind Agent Zero.

- Repository: [Agent Zero/agent-zero](https://github.com/agent0ai/agent-zero)
- Tags: internals
- Published: 2026-02-23

---

**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.

```python

# 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.

```python

# 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.

```python

# 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.

```python

# 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.

```python

# 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`.

```python

# 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`](https://github.com/agent0ai/agent-zero/blob/main/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`](https://github.com/agent0ai/agent-zero/blob/main/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`](https://github.com/agent0ai/agent-zero/blob/main/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`](https://github.com/agent0ai/agent-zero/blob/main/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:

```python

# 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

```

```python

# 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:
1. Extracts the module path `agents.profile` and function name `get_user_profile` from the placeholder function's metadata
2. Constructs an `RFCInput` object and computes the SHA-256 hash using the `A0_RFC_PASSWORD` secret
3. POSTs the encrypted payload to `http://<agent-b-host>:<port>/rfc`
4. Agent B verifies the hash, imports `agents.profile`, executes `get_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 `/rfc` endpoints, serializing function calls as JSON payloads wrapped in `RFCCall` structures.
- **Cryptographic Validation**: Every message includes a SHA-256 hash computed with the pre-shared `A0_RFC_PASSWORD`, ensuring integrity and authentication via `crypto.hash_data` and `crypto.verify_data`.
- **Dynamic Dispatch**: The server uses `importlib.import_module` and `getattr` to 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`](https://github.com/agent0ai/agent-zero/blob/main/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`](https://github.com/agent0ai/agent-zero/blob/main/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`](https://github.com/agent0ai/agent-zero/blob/main/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.