Native Image
TramAI uses JDK dynamic proxies for @AiService interfaces. GraalVM native-image builds need proxy metadata for every service interface instantiated at runtime.
What This Covers
- Generating GraalVM proxy-config.json for your @AiService interfaces
- Registering the right interfaces
- Spring Boot considerations
- Native image boundaries and smoke path
When You Need This
You need native image metadata when:
- building a GraalVM native binary of your TramAI application
- using
@AiServiceinterfaces that TramAI instantiates at runtime via dynamic proxies - deploying to serverless or container environments where fast startup matters
Minimum Setup: Metadata Generator
TramAI ships a small metadata generator: NativeImageProxyConfig.
import dev.tramai.core.nativeimage.NativeImageProxyConfig
import java.nio.file.Path
fun main() {
NativeImageProxyConfig.write(
outputPath = Path.of(
"src/main/resources/META-INF/native-image/com.example/app/proxy-config.json",
),
InvoiceAnalyzer::class,
IncidentSummarizer::class,
)
}
Run this generator before producing the native binary.
The generated JSON:
[
{ "interfaces": [ "com.example.InvoiceAnalyzer" ] },
{ "interfaces": [ "com.example.IncidentSummarizer" ] }
]
What to Register
Register every @AiService interface that TramAI will instantiate in the native binary:
- application service interfaces used through
Tramai.create(...) - Spring-discovered
@AiServiceinterfaces if you usetramai-spring
The rule: if TramAI creates a dynamic proxy for the interface at runtime, include it in proxy-config.json.
Spring Boot Considerations
If you use tramai-spring, register the same @AiService interfaces that Spring will ask TramAI to instantiate.
The metadata generator is the same — there is no Spring-specific path:
NativeImageProxyConfig.write(
outputPath = Path.of(
"src/main/resources/META-INF/native-image/com.example.app/proxy-config.json",
),
InvoiceAnalyzer::class,
)
Full Workflow
- identify every
@AiServiceinterface that will be instantiated at runtime - run
NativeImageProxyConfig.write(...)to generateproxy-config.json - place it under
META-INF/native-image/<group>/<artifact>/proxy-config.json - build your native image with that metadata on the classpath
Smoke Path
A reasonable smoke path:
- generate proxy metadata
- run normal JVM tests
- build one minimal native sample or smoke binary that instantiates at least one @AiService
- verify startup and basic operation
Limitations
- TramAI keeps runtime proxying in v1 — applications generate proxy metadata for their own interfaces
- This metadata covers TramAI's use of JDK dynamic proxies only
- Your app may still need additional reflection hints for:
- HTTP client native-image needs
- framework-specific reflection hints
- provider-library native-image constraints
- TramAI does not yet ship KSP-generated implementations or automatic full native-image AOT integration
Next Steps
- Troubleshooting — common native-image gotchas
- Configuration Reference — full config options
