Skip to main content

Documentation Index

Fetch the complete documentation index at: https://afk.arpan.sh/llms.txt

Use this file to discover all available pages before exploring further.

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.messaging import InternalA2AEnvelope

envelope = InternalA2AEnvelope(
    message_type="request",
    run_id="run-42",
    thread_id="thread-42",
    conversation_id="conversation-42",
    correlation_id="task-42",
    payload={"findings": ["fact 1", "fact 2"]},
    idempotency_key="task-42-research",
    source_agent="researcher",
    target_agent="writer",
)
FieldTypePurpose
message_typestrrequest, response, or event
run_idstrRun identifier for tracing
thread_idstrMemory thread identifier
conversation_idstrCross-run conversation identifier
payloaddictMessage data (any JSON-serializable content)
correlation_idstrGroups related messages in a workflow
idempotency_keystrDeduplication — same key = same message
source_agentstrName of the sending agent
target_agentstrName of the receiving agent
metadatadictJSON-safe tracing or routing metadata
timestamp_msintCreation timestamp in milliseconds

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(
    message_type="request",
    run_id=run_id,
    thread_id=thread_id,
    conversation_id=conversation_id,
    correlation_id=correlation,
    source_agent="coordinator",
    target_agent="researcher",
    payload={"query": "AI trends"},
    idempotency_key=f"{correlation}-research",
))

await send(InternalA2AEnvelope(
    message_type="request",
    run_id=run_id,
    thread_id=thread_id,
    conversation_id=conversation_id,
    correlation_id=correlation,
    source_agent="coordinator",
    target_agent="writer",
    payload={"topic": "AI trends"},
    idempotency_key=f"{correlation}-write",
))

Delivery store backends

Default. Fast, no setup. State lost on restart.
from afk.messaging import InMemoryA2ADeliveryStore

store = InMemoryA2ADeliveryStore()

Next steps

A2A Protocol

Cross-system agent communication.

Task Queues

Async job processing with queue backends.