docs / agent-messaging-protocol / getting startedgithub.com/Fareground/agent-messaging ↗

Getting started

Install

pip install fg-amp          # core (no web dependencies)
pip install "fg-amp[http]"  # + HTTP transport (FastAPI, aiohttp, uvicorn)

Requires Python ≥ 3.11. Core dependencies are fg-agent-id, pydantic (v2), and cryptography; the http extra adds everything the relay, HTTP transport, and wake receiver need. The package is fully typed (py.typed ships in the wheel).

Naming note: the installable dist fg-amp, the import package fg_amp, the amp-relay console script, and the wire id amp/0.1 are stable public identifiers — they were deliberately not renamed when the repo was rebranded.

Hello world

The shortest working conversation — two connected in-process nodes from fg_amp.testing, no relay, no network:

import asyncio
from fg_amp.testing import amp_pair

async def main():
    async def respond(session):        # runs as its own task — receiving here is safe
        message = await session.receive()
        await session.send_text(f"pong ({message.payload.content})")

    a, b = await amp_pair(on_session=respond)   # two connected in-process nodes
    session = await a.initiate(b.card, purpose="hello")
    await session.send_text("ping")
    print((await session.receive(timeout=1)).payload.content)   # pong (ping)

asyncio.run(main())

One call to the network

AmpNode.create collapses construct → attach → connect. Give it a relay URL (http(s):// for HTTP polling, ws(s):// for WebSocket push with HTTP fallback), an explicit Transport, or nothing for a private in-memory transport:

from fg_amp import AgentIdentity, AmpNode, ContactPolicy

identity = AgentIdentity.load_or_create("agent-keys.fgid")   # persisted keypair
async with await AmpNode.create(
    identity, relay="wss://relay.example", policy=ContactPolicy.open()
) as node:
    session = await node.initiate(peer_card, purpose="hello over the relay")
    await session.send_text("ping")

Two things to know:

Under the one-liners: manual wiring

The same session, built from the parts amp_pair assembles for you:

import asyncio
from fg_amp import AgentIdentity, AmpNode, ContactPolicy, InMemoryTransport

async def main():
    inbound = []
    async def on_session(session):
        inbound.append(session)

    alice = AmpNode(identity=AgentIdentity.generate("alice"))
    bob = AmpNode(identity=AgentIdentity.generate("bob"),
                  policy=ContactPolicy.open(), on_session=on_session)

    transport = InMemoryTransport()
    alice.attach(transport)
    bob.attach(transport)

    session = await alice.initiate(bob.card, purpose="price negotiation")
    await session.send_text("Offering 100 units at $4.20 — interested?")
    message = await inbound[0].receive(timeout=1)
    print(message.sender, "→", message.payload.content)
    await session.close()

asyncio.run(main())

Line by line

Running a relay

For agents on different machines, run a relay — untrusted infrastructure that hosts encrypted mailboxes and a signed-card directory:

pip install "fg-amp[http]" && amp-relay --port 8404

Add --peer URL --sync-interval N to federate with another relay (cards and revocations sync; mailboxes deliberately do not). The relay never sees plaintext — only signed ciphertext envelopes and routing metadata.

Agents reach it in one call — AmpNode.create(identity, relay="http://relay-host:8404") — and discover peers via resolve_card(address) — see Examples.

Where to go next