This cookbook provides deterministic implementation patterns for the current IO runtime. Use these patterns when writing examples, agent workflows, or production-oriented AIC programs.
Use std.io read APIs and branch on IoError instead of panicking.
import std.io;
fn read_name() -> String effects { io } {
match prompt("Name: ") {
Ok(value) => value,
Err(EndOfInput) => "guest",
Err(InvalidInput) => "guest",
Err(Io) => "guest",
}
}
Reference: examples/io/interactive_greeter.aic.
Prefer handle APIs for multi-line workflows.
import std.fs;
fn unwrap_handle(v: Result[FileHandle, FsError]) -> FileHandle {
match v {
Ok(handle) => handle,
Err(_) => FileHandle { handle: 0 },
}
}
fn process() -> Int effects { fs } {
let reader = unwrap_handle(open_read("in.txt"));
let first = file_read_line(reader);
let _ = first;
let _ = file_close(reader);
0
}
References:
examples/io/file_processor.aicexamples/io/line_reader.aic
Use std.io.stream_copy when you want to move bytes between a reader and writer without hand-rolling the loop.
import std.io;
fn relay(reader: Reader, writer: Writer) -> Int effects { io } {
match stream_copy(reader, writer) {
Ok(count) => count,
Err(_) => 0,
}
}
Reference: examples/io/stream_copy.aic.
Use stdout for user-facing status, stderr for operator diagnostics, and std.fs for persistent logs.
import std.io;
import std.fs;
fn log_once(path: String) -> Int effects { io, fs } {
let _ = append_text(path, "INFO startup\n");
println_str("INFO startup");
eprint_str("WARN startup");
flush_stdout();
flush_stderr();
0
}
Reference: examples/io/log_tee.aic.
Use std.env.get for optional values and keep defaults local.
import std.env;
fn config_token() -> String effects { env } {
match get("AIC_TOKEN") {
Ok(value) => value,
Err(NotFound) => "default-token",
Err(_) => "default-token",
}
}
Reference: examples/io/env_config.aic.
Use run/pipe for short commands, and run_with when cwd/env/stdin must be controlled.
import std.proc;
import std.vec;
fn pipeline_demo() -> Result[ProcOutput, ProcError] effects { proc, env } {
let mut stages: Vec[String] = vec.vec_of("printf 'hello'");
stages = vec.push(stages, "cat");
pipe_chain(stages)
}
Reference: examples/io/subprocess_pipeline.aic.
Use std.retry for exponential backoff with optional jitter, and with_timeout for deadline checks around operations.
import std.retry;
fn default_policy() -> RetryConfig {
default_retry_config()
}
References:
examples/io/retry_with_jitter.aicdocs/examples/retry-workflow.md
Use ByteBuffer for protocol layouts that require endian-aware integers, null-terminated strings, and backpatching.
import std.buffer;
fn frame() -> Result[ByteBuffer, BufferError] {
match new_growable_buffer(32, 512) {
Err(err) => Err(err),
Ok(buf) => {
let write_len = buf_write_i32_be(buf, 0);
let write_kind = buf_write_u8(buf, 1);
let write_tag = buf_write_cstring(buf, "msg");
let end = buf_position(buf);
let patch_len = buf_patch_u32_be(buf, 0, end);
let _a = write_len;
let _b = write_kind;
let _c = write_tag;
let _d = patch_len;
Ok(buf)
}
}
}
Reference: examples/data/binary_protocol.aic.
Use buf_close when a frame buffer is no longer needed in long-lived workers to release memory eagerly.
Use byte-level checks for digest validation and prefer typed decode/derive error handling.
import std.crypto;
import std.bytes;
fn bytes_or_empty(v: Result[Bytes, CryptoError]) -> Bytes {
match v {
Ok(value) => value,
Err(_) => bytes.empty(),
}
}
fn scram_seed(password: String) -> Bytes {
bytes_or_empty(pbkdf2_sha256(password, bytes.from_string("salt"), 4096, 32))
}
Reference: examples/crypto/pg_scram_auth.aic.
When cross-platform behavior differs, branch on typed errors.
import std.net;
fn connect_or_skip(addr: String) -> Int effects { net } {
match tcp_connect(addr, 500) {
Ok(_) => 1,
Err(Io) => 0,
Err(_) => 0,
}
}
Current runtime caveats to account for:
- Windows
std.net: TCP loopback plus async accept/recv wait/cancel/shutdown client-transport paths are smoke-backed; UDP/DNS/socket-tuning share the backend but are not yet Windows-smoke-backed, and unsupported socket-option paths can surfaceNetError::Io. - Windows
std.proc:spawn,run,run_with,run_timeout,pipe, andpipe_chaincan surfaceProcError::Io;wait,kill, andis_runningcan surfaceProcError::UnknownProcess. - Windows
std.signal: unsupported and returnsSignalError::UnsupportedPlatform.
Use std.http_server for synchronous request/response shaping and std.router for deterministic route matching; pair them with std.config when request-driven startup config must be loaded before accepting traffic.
import std.http_server;
import std.router;
import std.config;
fn ready() -> Int effects { net, fs, env } {
let cfg = load_env_prefix("APP_");
let _ = cfg;
let router0 = match new_router() {
Ok(value) => value,
Err(_) => return 0,
};
let router1 = match add(router0, "GET", "/health", 1) {
Ok(value) => value,
Err(_) => return 0,
};
let response = text_response(200, "ready");
let _ = router1;
let _ = response;
1
}
Reference: examples/io/http_router.aic and examples/io/config_loading.aic.
Use std.tls for encrypted transport and branch on TlsError for deterministic behavior in environments that do not provide TLS backend support.
import std.tls;
import std.bytes;
fn tls_connected(stream: TlsStream) -> Int effects { net } {
let sent = tls_send_bytes(stream, bytes.from_string("HEAD / HTTP/1.0\n\n"));
let recv = tls_recv_bytes(stream, 256, 3000);
let closed = tls_close(stream);
let _a = sent;
let _b = recv;
let _c = closed;
1
}
fn tls_probe(addr: String, host: String) -> Int effects { net } {
let cfg = unsafe_insecure_tls_config(Some(host));
match tls_connect_addr(addr, cfg, 3000) {
Ok(stream) => tls_connected(stream),
Err(ProtocolError) => 0,
Err(Io) => 0,
Err(_) => 0,
}
}
Reference: examples/io/tls_connect.aic.
Policy: docs/security-ops/tls-policy.v1.json.
Normalize module-specific errors to machine-readable secure error metadata for deterministic branching.
import std.secure_errors;
import std.buffer;
fn protocol_category_or_unknown(v: Result[Int, BufferError]) -> String {
match v {
Ok(_) => "ok",
Err(err) => secure_errors.buffer_error_info(err).category,
}
}
Reference: examples/io/secure_error_contract.aic.
Contract: docs/errors/secure-networking-error-contract.v1.json.
Use the canonical replay example when implementing production-style secure protocol clients with deterministic failure semantics.
import std.secure_errors;
fn classify(info: SecureErrorInfo) -> String {
info.code
}
What this flow covers:
- startup/binary framing (
std.buffer) - SCRAM proof derivation (
std.crypto) - TLS secure-default + unsafe audit path (
std.tls) - retry and timeout behavior (
std.retry) - pool-capacity contract semantics (
PoolErrorContract)
Reference example: examples/io/postgres_tls_scram_reference.aic.
Replay artifact: docs/security-ops/postgres-tls-scram-replay.v1.json.