alkcall
Call + channels RPC: structured JSON operations, streaming subscriptions, service discovery, and N-channel multiplexing over one transport stream.
This crate unifies the call protocol and the channels protocol, plus the
vendored core types formerly in alknet-core. It is a pure protocol crate
— no networking, no transport dependencies. Downstream crates (alktty,
alktunnels, alktrader) compose on top of it.
Quick start
Producer — register an operation and run a dispatcher
use Arc;
use ;
use ;
use ;
let registry = new;
registry.register.unwrap;
let registry = new;
let provider: = /* your identity provider */;
let adapter = new;
// adapter implements ProtocolHandler — call adapter.handle(connection, &auth).await
Consumer — call an operation
use Connection;
use CallConnection;
let connection = from_bidi;
let conn = new;
let response = conn.call.await;
assert!;
Channels — open a channel and call through channel 0
use ChannelClient;
use Connection;
let connection = from_bidi;
let client = from_connection.await?;
let response = client.call_open_op.await;
from_call — discover and import remote operations
use ;
let registrations = from_call.await?;
for reg in registrations
// now call remote ops as if they were local
let response = conn.call.await;
Serving your own ops as a connected consumer
The call protocol is symmetric — both sides of a connection can serve
ops. A ChannelClient built with from_connection is a pure consumer
(inbound call.requested frames are dropped); pass a ServingConfig
to also serve your registry to the peer, and use op/register to
announce which ops you serve:
use Arc;
use ;
use install_bootstrap_discovery;
let registry = new;
// ... register your ops on the registry, then:
install_bootstrap_discovery?;
let client = from_connection_with_serving.await?;
// peer-callable ops resolve against `registry` on channel 0;
// `client.call_open_op` still works — both directions share the pump
Architecture
alkcall is a pure protocol crate — no networking, no transport dependencies. It provides the call and channels protocols as a library. Downstream crates compose on top of it in a layered dependency chain.
| Role | Call protocol | Channels protocol |
|---|---|---|
| Producer | Registers ops on an OperationRegistry, runs a Dispatcher |
Runs a ChannelsAdapter, registers openable ALPNs via ChannelCore::register_openable |
| Consumer | Uses CallConnection to call ops, uses from_call to discover/import remote ops; may also serve its own ops (from_connection_with_serving) |
Uses ChannelClient to open channels via call_open_op + open_channel |
| Hub | Both: runs a Dispatcher for ops it produces, holds CallConnections to spokes for ops it consumes |
Both: runs a ChannelsAdapter for inbound connections, holds ChannelClients to spokes |
| Spoke / Worker | Both: produces ops (its own services), consumes hub ops | Both: produces channels (TTY, tunnel), may consume hub channels |
A single process can be a producer of some ops, a consumer of others, a
channel opener for TTY, and a channel acceptor for tunnels — all on the
same alk/channels connection.
Documentation
- Architecture docs — the authoritative spec: ADRs, wire formats, protocol contracts, and composition patterns.
- API docs — full crate documentation on docs.rs.
- Open questions — tracked deferred decisions and feature gaps.
License
MIT OR Apache-2.0