bindings/python/docs/reference/best-practices.md
Adapted from thoughts/shared/plans/BEST_PRACTISES.md for this package. This is the bar for
review on every change; ../../AGENTS.md states the handful of invariants that apply to
almost every task, this file is the fuller checklist.
(See the repo-root AGENTS.md "Business logic layering rules" for the cross-SDK version of
this — commons owns truth, the SDK layer owns platform I/O and composition. Python-specific
applications of it:)
_streaming.py), the composition the spec puts behind one verb
(messages, grammar, the tool loop), the CLI/server, and honesty in docs/API surface.runanywhere/server/ and runanywhere/cli/ are adaptation
over the namespaces — no new AI business logic in a FastAPI route or a CLI handler. If a
command needs multi-step orchestration, push it into the namespace or into commons.llm.generate loads and downloads what it needs; never make a caller
assemble register → download → load themselves.idl/errors.proto / rac_error.h. Keep ErrorCode /
ErrorCategory exhaustive relative to the IDL and map categories with
category_for_code as a faithful port of commons rac_result_to_proto_category
(AUTH is only 320–329; unmapped failures → INTERNAL, not UNSPECIFIED).RAC_FRAMEWORK_*,
RAC_MODEL_CATEGORY_*), not proto wire values. Name them and pin them in tests.runanywhere/_proto/; regenerate via
idl/codegen/generate_python.sh (wired into generate_all.sh). Never hand-edit
_pb2.py._native/_core.pyi in lockstep with native/module.cpp bindings.initialize runs the control plane only with credentials: authenticate + telemetry flush
over a stdlib-urllib transport (no libcurl). Keyless, it does no network work;
api_key/base_url map to that handshake. The HTTP server's optional Bearer api_key
is a separate thing, configured on serve() / the CLI.not_implemented naming the exact missing rac_*
symbols. Never return a plausible empty result instead.take_handle_when_idle
(including VAD). Blocking ops take begin_op / OpScope leases.Event and call component cancel
(cancel_generate / cancel_generate_vlm) via _streaming.on_stop so decode stops
promptly, not only on the next token callback._GenerationGuard); a second concurrent
generate is a programming error → invalid_state, not a silent queue._fseeki64 / _ftelli64 (plain ftell/long truncates >2GB)... / absolute paths (secure_key_ok
_validate_secure_key).SDKException only on the public surface; map I/O/download failures to
STORAGE_ERROR (or the correct category), not GENERATION_FAILED.storage_error, model_load_failed, …) so code/category stay
consistent.FakeCore / no network / no real keys / no models required for
the unit suite.tests/ dir — local verification should match that shape when touching
packaging.generation_failed for disk/tar/HTTP I/O.take_handle while another thread may still be inside rac_*.