Skip to main content
AFK’s internal messaging system lets agents communicate via structured envelopes with at-least-once delivery and idempotency. Use it when agents in the same system need to exchange data reliably.

Message lifecycle

The InternalA2AEnvelope

Every message is wrapped in a typed envelope:
from afk.a2a import InternalA2AEnvelope

envelope = InternalA2AEnvelope(
    sender="researcher",
    receiver="writer",
    payload={"findings": ["fact 1", "fact 2"]},
    correlation_id="task-42",         # ← Group related messages together
    idempotency_key="unique-msg-01",  # ← Prevent duplicate processing
)
FieldTypePurpose
senderstrName of the sending agent
receiverstrName of the receiving agent
payloaddictMessage data (any JSON-serializable content)
correlation_idstrGroups related messages in a workflow
idempotency_keystrDeduplication — same key = same message
created_atdatetimeTimestamp of creation
attemptintCurrent delivery attempt number

Delivery behavior

  1. Sender creates and submits the envelope
  2. Delivery store checks the idempotency key (rejects duplicates)
  3. Message is delivered to the receiver
  4. Receiver processes and ACKs
  5. Store marks as delivered
Result: Message processed exactly once.

Idempotency and correlation

Always set an idempotency_key. Without it, retry deliveries can cause duplicate processing. Use a deterministic key derived from the task context (e.g., f"{task_id}-{step_name}").
Correlation IDs group related messages across a workflow. When debugging, filter by correlation_id to see the full message chain for a task.
# All messages in this workflow share the same correlation_id
correlation = f"analysis-{run_id}"

await send(InternalA2AEnvelope(
    sender="coordinator", receiver="researcher",
    payload={"query": "AI trends"},
    correlation_id=correlation,
    idempotency_key=f"{correlation}-research",
))

await send(InternalA2AEnvelope(
    sender="coordinator", receiver="writer",
    payload={"topic": "AI trends"},
    correlation_id=correlation,
    idempotency_key=f"{correlation}-write",
))

Delivery store backends

Default. Fast, no setup. State lost on restart.
from afk.a2a import InMemoryDeliveryStore
store = InMemoryDeliveryStore()

Next steps