Protobuf IDL & Code Generation
Relevant source files
The following files were used as context for generating this wiki page:
The Protobuf Interface Definition Language (IDL) serves as the single schema root for all cross-platform types in the RunAnywhere monorepo. This schema defines model configurations, error types, SDK events, and AI modality settings (LLM, VLM, STT, TTS, VAD). The project uses these definitions to ensure type safety and wire compatibility across multiple programming languages and platforms.
The code generation system renders these .proto files into language-specific bindings for Swift, Kotlin, TypeScript, Dart, C++, and Python. This process replaces hand-written helpers with generated code, ensuring that the same data structures and validation logic apply regardless of the SDK being used.
Sources: idl/AGENTS.md:7-13, AGENTS.md:143-147
Architecture and Schema Design
The IDL consists of 39 .proto files located in the idl/ directory, all using the runanywhere.v1 package. These files define the contract for every cross-platform component. While tool_calling.proto contains a service block, it represents a logical contract for parsing and validation rather than a gRPC wire transport. All inter-process communication is handled via the in-process C callback path defined in the C++ core.
Sources: idl/AGENTS.md:7-10, idl/AGENTS.md:43-48
Schema Stability and Versioning
The project enforces strict wire-compatibility rules. Developers must never renumber or reuse field numbers for wire-stable or persisted messages, such as those in model_types.proto and sdk_events.proto. Numeric values in errors.proto must exactly match the core C++ headers.
Schema changes are tracked via:
idl/VERSION: A hand-maintained semver file.idl/SCHEMA_LOCK: A gate that prevents drift between the IDL and generated code.
Sources: idl/AGENTS.md:13, idl/AGENTS.md:27-36
Data Flow Overview
The following diagram illustrates how the Protobuf IDL is transformed into usable code across the various SDKs.
The diagram shows the central role of the IDL files in generating bindings that feed into platform-specific SDKs and the central C++ core.
Sources: idl/AGENTS.md:11-13, AGENTS.md:143-147
Code Generation Toolchain
The primary entry point for code generation is the idl/codegen/generate_all.sh script. This script orchestrates various sub-generators to produce the required output for each target language.
Target Generators
Each language uses specific tools and post-processors:
- TypeScript: Uses
ts-prototo generate message types andAsyncIterablestream wrappers. - Kotlin: Uses
Wireto generate message types. - C++: Emits
rac_defaults_generated.hfor default values. - Python: Generates
_pb2.pyfiles.
Sources: idl/AGENTS.md:11-13, bindings/proto-ts/AGENTS.md:23-28, bindings/kotlin/AGENTS.md:104-110
Convenience Generators
In addition to standard Protobuf message generation, the system includes "Convenience Generators" (generate_{lang}_convenience.py). These post-process the descriptor set to emit accessors for:
defaults(): Provides default values defined in the IDL.validate(): Performs bounds and requirement checks.displayName()andwireString(): Handle metadata and analytics.
Sources: idl/AGENTS.md:54-62
Custom Field Annotations
The system uses nine custom FieldOptions and EnumValueOptions extensions in the 50000–99999 range. These are defined in rac_options.proto.
| Option | Purpose |
|---|---|
rac_default | Specifies the default value for a field. |
rac_required | Marks a field as mandatory for validation. |
rac_min / rac_max | Defines integer bounds. |
rac_min_float / rac_max_float | Defines floating-point bounds. |
rac_display_name | Provides a human-readable name. |
rac_analytics_key | Defines the key used in telemetry. |
rac_wire_string | Provides the string representation for enums. |
| Sources: idl/AGENTS.md:54-58, bindings/react-native/AGENTS.md:139-142 |
Language-Specific Implementation
TypeScript (Web & React Native)
The @runanywhere/proto-ts package contains the generated TypeScript bindings. Most files in this package are codegen output and are gitignored. It provides AsyncIterable adapters to convert subscribe-based native transports into lazy iterables.
Sources: bindings/proto-ts/AGENTS.md:12-21, bindings/proto-ts/AGENTS.md:83-85
Kotlin (Android)
Generated bindings for Kotlin live in src/main/kotlin/com/runanywhere/sdk/generated/. These include Wire-generated classes and the RADefaultsPool. The generateIdlKotlinBindings Gradle task triggers the generation process.
Sources: bindings/kotlin/AGENTS.md:104-108
Swift (iOS & macOS)
Swift bindings are used by both the native Swift SDK and the React Native SDK via NitroModules. The sync-dist-repo.sh script ensures that generated code is included when cutting the standalone Swift distribution repository.
Sources: bindings/swift/scripts/sync-dist-repo.sh:17-21, bindings/react-native/AGENTS.md:105-110
Validation and Linting
The IDL is subject to linting and breaking change checks using buf.
- Linting: Configured in
buf.yamlusing theSTANDARDruleset. - Breaking Changes: Checked against the
WIREcategory to ensure backwards compatibility.
buf lint idl
buf breaking idl --against '.git#branch=main,subdir=idl'
Sources: idl/AGENTS.md:68-76
The Protobuf IDL and code generation framework ensures that the complex multi-SDK environment remains synchronized with a single source of truth, facilitating cross-platform feature parity and reducing manual implementation errors.