A compact map of the surface. The raw method names line up across languages: Rust
groups them under an accessor and takes option structs, while Node and Python put
each one on the client with plain arguments. Node and Python also expose native JSON
handles from the main import (forge.queue<T>("emails"), forge.queue("emails"))
so app payloads stay typed without a separate overlay.
Use raw methods for bytes and exact cross-language contracts. Use handles when the
payload is app JSON and you want the name, codec, and type to stay together.
Every failure maps onto one of these. The retryable column says whether trying again
might succeed.
Error
Retryable
Meaning
Config
no
Bad configuration. Only happens during init().
Unavailable
yes
A transient backend outage (timeout, dropped connection).
NotFound
no
The requested entity doesn’t exist.
Precondition
no
A condition failed: a CAS mismatch, a lost lease, a duplicate dedup_id. Re-read state and decide.
Limit
no
A size or quota limit was exceeded.
Invalid
no
A bad argument or malformed input.
Backend
sometimes
Anything else, carrying its own retryable flag.
In Rust these are variants of ForgeError with an is_retryable() method. Node
throws an Error. Python raises typed exceptions that subclass forgelib.ForgeError
(NotFound, Invalid, Limit, Precondition, Unavailable, Config, Backend).
Forge ships memory and Postgres for every primitive, plus filesystem for blob. If
you need something else, like Redis or S3, implement that primitive’s trait and
inject it with the Rust builder. Every other primitive stays on its configured
backend.
letforge= forgelib::Forge::builder()
.kv(my_redis_kv) // kv runs on your backend; the rest stay on Postgres
Forge’s API isn’t in any model’s training data, so a coding agent won’t know it
cold. Install the companion skill and the agent learns which primitive fits which
task and the idioms for each language before it writes Forge code.