Core concepts¶
The pieces¶
libpolycall (polycall_static/polycall_shared) — the reusable
native library. It implements configuration parsing (legacy and native
schema-v2), the polycall_rpc v1 runtime, and the public C API. It has no
main() of its own.
polycall — the operator CLI (src/cli/ + src/main.c), a thin
dispatcher over a fixed command registry (src/cli/cli_commands.c) that
translates parsed command-line options into calls against libpolycall
and renders the result as human text or --format json. See the
CLI reference.
The runtime (polycall_runtime_t) — created by polycall start (or an
embedding application calling polycall_runtime_create/
polycall_runtime_serve). It binds --endpoint host:port, accepts
connections (one thread per connection), authenticates control actions
against --auth-token, and routes each request frame to whichever
registered operation matches its service.operation.
An operation (polycall_op_desc_t) — a service, operation name
pair with a handler function, an input/output schema hint, and an
idempotent flag clients use to decide whether to retry. Two are
built in: inventory.get and debug.sleep. More can be added at runtime
with no core rebuild via start --load PATH (a shared library exporting
polycall_ops_register) — see docs/PLUGINS.md.
Registering the same service.operation twice — from two plugins, or a
plugin and a built-in — is always refused, never "last one wins".
A reference client (tools/rpc-clients/{node,python,go,java}/) —
minimal, stdlib-only implementations of the polycall_rpc v1 wire
protocol used by this repository's own conformance tests
(tests/conformance/run.sh) and the ledger demo.
They exist to prove the protocol is genuinely cross-language, not to be
an installable SDK — see Language integration.
A config provider (c:/node:/python:) — separate from a runtime
client: code that produces a validated schema-v2 configuration envelope
for config validate/config show, never touches the network, and never
starts a service. See the Polycallfile reference.
Request/response, not a shared address space¶
A call round trip is one TCP connection, one framed request, one framed
response — never a retry, even for a deterministic operation. The frame
is a fixed 16-byte header (magic, type, correlation, length) plus a UTF-8
JSON payload; no C struct layout or pointer ever crosses the socket. See
docs/RPC.md for the exact byte layout and the transport
→ exit-code map every client (C CLI included) implements identically.
caller --(service, operation, deadline_ms, input JSON)--> runtime --dispatch--> operation handler
caller <---------(output JSON / structured error)-------- runtime <-------------------┘
Typed exit codes, not just a boolean¶
Every command maps its outcome onto one shared exit-code contract (0 OK,
1 runtime failure, 2 usage, 3 config, 4 unsupported, 5 transport, 6
deadline, 7 auth — see the CLI reference).
An operation handler itself returns one of four status classes
(POLYCALL_OP_OK/ERR_INPUT/ERR_NOTFOUND/ERR_INTERNAL/ERR_DEADLINE),
which the runtime maps onto those same codes centrally — a handler never
picks a process exit code itself.
Configuration is explicit, never merged from a search path¶
Both configuration paths — the legacy Polycallfile loader and the
native schema-v2 providers — take an explicit path or selector. There is
no parent-directory search, no home-directory fallback for Polycallfile
itself, and selecting a node:/python: provider only ever runs the
exact module and runner script named — never a directory scan. doctor
never evaluates a provider or starts a service; it only reports build,
platform, ABI, and core-capability facts.
Telemetry is a side channel, not part of the protocol¶
start/call automatically emit GUID + timestamp correlated events to a
JSONL sink (.polycall/telemetry.jsonl by default) — this is separate
from the polycall_rpc v1 wire and never affects a call's outcome or
timing budget. See the CLI reference.