Skip to content

Go Packages

Exported packages: host, dht, protocol, identity, crypto. Module path github.com/a2al/a2al.

For the daemon’s REST and MCP interfaces and the Python sidecar, see the REST API; for the concepts, see the Architecture Overview.

LevelPackageUse when
Node runtimegithub.com/a2al/a2al/hostDHT + QUIC, publish / resolve / connect
DHT onlygithub.com/a2al/a2al/dhtYou bring your own transport and only need routing and STORE/FIND
Daemona2aldREST, Web UI, MCP — do not import host unless you are embedding

Wraps a DHT node, a UDP mux or a separate QUIC socket, NAT reflection (natsense), ICE, and optional TURN.

Wildcard ListenAddr / QUICListenAddr values (:4121, 0.0.0.0:port) bind dual-stack; a specific IPv4 address stays IPv4-only. DisableIPv6 forces udp4 (a library option only, not a daemon TOML key).

FieldMeaning
KeyStoreRequired. Exactly one Address.
ListenAddrUDP binding for the DHT (default ":4121"). Dual-stack when no specific host is given.
QUICListenAddrEmpty shares the socket with the DHT (mux); non-empty binds QUIC separately.
PrivateKeyEd25519 private key for QUIC / TLS; otherwise taken from EncryptedKeyStore.Ed25519PrivateKey.
MinObservedPeersHow many peers must agree on a reflected address (default 3).
FallbackHostAddress to advertise when neither binding nor reflection is conclusive.
DisableUPnPSkip IGD mapping of the QUIC port (IPv4).
DisableIPv6Force IPv4-only.
ICESignalURL / ICESignalURLsICE WebSocket hub; ICESignalURLs wins when non-empty, and its first address is also written into EndpointPayload.Signal.
ICESTUNURLsstun: addresses; leave empty to use public STUN when no TURN is configured.
ICETURNURLsLegacy turn: with inline credentials; prefer TURNServers.
TURNServersExternal TURN: URL, Username, Credential, CredentialType (static / hmac / rest_api). Credentials are minted per ICE session and never published.
ICEPublishTurnsDeprecated. New nodes do not write turns[] to the DHT.
DisableRelayWhen true, TURN relaying is off by default; can still be toggled per call via DialOptions.DisableRelay. Defaults to false.
ICENetworkTypesICE network types; defaults to UDP4 + UDP6.
Logger*slog.Logger, defaults to slog.Default().

The internal DHT node’s RecordAuth requires either a self-signature or a valid delegation.

  1. host.New(cfg)
  2. h.Node().BootstrapAddrs(ctx, []net.Addr{…}) — seeds are ip:port
  3. Optionally ObserveFromPeers
  4. PublishEndpoint / Resolve / ConnectFromRecord / Accept
  5. h.Close()
MethodWhat it does
PublishEndpoint / PublishEndpointForAgentSign a single multi-candidate quic:// payload (v4/v6, plus the mapped result when UPnP is enabled) and STORE it.
ResolveIterative lookup → *protocol.EndpointRecord.
ConnectOpen a QUIC connection to a single UDP address and send an agent-route frame.
ConnectFromRecord / ConnectFromRecordForHappy Eyeballs over the record’s endpoints; falls back to ICE when direct attempts fail and a signaling address is present. Returns (conn, isRelayed, err); returns ErrRelayRequired when a relay is configured but disabled and the direct attempt fails.
AcceptAccept an inbound QUIC connection → *AgentConn.
QUICDialTargets / FirstQUICAddrOrdered UDP targets from a record.
BuildEndpointPayloadProduce candidates without STORE.
SymmetricNATReachabilityHintNon-empty when a symmetric NAT is detected (a relay may still be needed).
RegisterAgent / RegisterDelegatedAgent / UnregisterAgent / RegisteredAgentsAttach more AIDs to the same listener.
SendMailbox / PollMailbox (and ForAgent variants)Encrypted notes.
RegisterTopic(s) / SearchTopic(s) (and ForAgent variants)Capability-name rendezvous.
StartDebugHTTP / DebugHTTPHandlerRead-only JSON.
CloseShut down QUIC, the mux, the DHT, and UPnP mappings.

AgentConn embeds quic.Connection and exposes Local / Remote AIDs.

After TLS, the client writes a 4-byte magic + the 21-byte target AID on stream 0.

  • a2r2 (current): a length-prefixed control message, after which both sides FIN that stream; data travels on subsequent streams. This is what host implements.
  • a2r1: still accepted inbound (frame parsing only).

TLS SNI serves as a secondary hint when several agents share a listener.

FieldMeaning
TransportRequired.
KeystoreRequired. One identity.
OnObservedAddrCallback for reflected addresses.
RecordAuthRuns after VerifySignedRecord; empty means no permission check.

BootstrapAddrs accepts ip:port only. PublishMailboxRecord / PublishTopicRecord STORE records at the recipient’s or topic’s NodeID respectively.

PackageContents
github.com/a2al/a2alAddress, NodeID, ParseAddress, NodeIDFromAddress
…/cryptoKeyStore, EncryptedKeyStore, AddressFromPublicKey, GenerateEd25519
…/identitySignDelegation, VerifyDelegation, Ethereum / Paralism helpers
ItemPurpose
SignedRecordCBOR wire format, optional Delegation.
EndpointPayloadEndpoints (quic://host:port or quic://[v6]:port), NatType, Signal, Signals. Turns is decoded from old records only and is never written on new publishes.
SignEndpointRecord / SignEndpointRecordDelegatedSigned by the master key vs. by an operational key.
ParseEndpointRecord / VerifySignedRecordVerify signature, TTL, and authority.
MailboxRecTypeMailbox 0x80; X25519 + AES-GCM helpers.
TopicRecTypeTopic 0x10; key is SHA-256("topic:" ‖ name); DiscoverFilter.

timestamp + TTL must cover the current time.

Default(), Validate(), LoadFile / Save, ApplyEnv. For an example see doc/a2ald-config.example.toml in the repository; for field descriptions see Configuration.

A library-mode Host / Node should bind dht.DebugHTTPAddr (127.0.0.1:2634); the daemon exposes the same set of endpoints under /debug/ on the admin address.

PathSource
/debug/identity, /debug/routing, /debug/store, /debug/statsdht.Node
/debug/hostHost: QUIC bindings, registered agents, NAT summary

Sense(): TrustedUDP / TrustedUDPAll (v4 and v6), InferNATType, InferV6Reach. Small test networks can lower MinAgreeing.

Terminal window
go test -vet=off -count=1 ./...

Each directory under examples/ has its own go.mod and replace.

ForPage
Getting-started guide and examplesGo SDK
Protocol and wire formatProtocol Specification