The Modal client is the main entry point for interacting with Modal resources from Go. It provides services for managing Apps, Sandboxes, Functions, Images, and other Modal resources.
Creating a client
The simplest way to create a client is using the default configuration:
import modal " github.com/modal-labs/modal-client/go "
mc , err := modal . NewClient ()
if err != nil {
log . Fatalf ( "Failed to create client: %v " , err )
}
This reads credentials from environment variables (MODAL_TOKEN_ID and MODAL_TOKEN_SECRET) or the ~/.modal.toml configuration file.
Client with custom options
For more control, use NewClientWithOptions to customize the client:
client , err := modal . NewClientWithOptions ( & modal . ClientParams {
TokenID : "ak-YOUR_TOKEN_ID" ,
TokenSecret : "as-YOUR_TOKEN_SECRET" ,
Environment : "main" ,
})
if err != nil {
log . Fatalf ( "Failed to create client: %v " , err )
}
Client parameters
The ClientParams struct supports several configuration options:
type ClientParams struct {
// Authentication credentials
TokenID string
TokenSecret string
// Environment to connect to (defaults to "main")
Environment string
// Custom configuration (advanced use)
Config * config
// Custom logger for debugging
Logger * slog . Logger
// Custom gRPC client for testing
ControlPlaneClient pb . ModalClientClient
ControlPlaneConn * grpc . ClientConn
// Custom gRPC interceptors for telemetry
GRPCUnaryInterceptors [] grpc . UnaryClientInterceptor
GRPCStreamInterceptors [] grpc . StreamClientInterceptor
}
Client services
The client exposes services for different Modal resource types:
Apps
Sandboxes
Functions
Images
Volumes
Secrets
Queues
Classes
// Get or create an app
app , err := mc . Apps . FromName ( ctx , "my-app" , & modal . AppFromNameParams {
CreateIfMissing : true ,
})
Custom observability
Add custom gRPC interceptors for telemetry, tracing, and observability:
import (
" context "
" log "
" time "
modal " github.com/modal-labs/modal-client/go "
" google.golang.org/grpc "
)
// Custom unary interceptor for logging
func loggingInterceptor () grpc . UnaryClientInterceptor {
return func (
ctx context . Context ,
method string ,
req , reply interface {},
cc * grpc . ClientConn ,
invoker grpc . UnaryInvoker ,
opts ... grpc . CallOption ,
) error {
start := time . Now ()
err := invoker ( ctx , method , req , reply , cc , opts ... )
log . Printf ( "gRPC call: %s , duration: %v , error: %v " , method , time . Since ( start ), err )
return err
}
}
func main () {
mc , err := modal . NewClientWithOptions ( & modal . ClientParams {
GRPCUnaryInterceptors : [] grpc . UnaryClientInterceptor {
loggingInterceptor (),
},
})
if err != nil {
log . Fatalf ( "Failed to create client: %v " , err )
}
// Use client...
}
Custom interceptors are appended after Modal’s built-in interceptors. The Modal gRPC API is not considered a public API and can change without warning.
Closing the client
Always close the client when done to clean up gRPC connections:
mc , err := modal . NewClient ()
if err != nil {
log . Fatalf ( "Failed to create client: %v " , err )
}
defer mc . Close ()
// Use the client...
Client version
Get the SDK version:
version := mc . Version ()
fmt . Printf ( "Modal Go SDK version: %s \n " , version )
Migration from v0.4 to v0.5
The v0.5 release introduced breaking changes. Key differences:
Client initialization changed
modal . InitializeClient ( modal . ClientOptions { ... })
modal . NewClient ()
// or
modal . NewClientWithOptions ( & modal . ClientParams { ... })
Resources accessed via client services
modal . AppLookup ( ctx , "my-app" , & modal . LookupOptions { ... })
modal . SandboxFromId ( ctx , "sb-123" )
mc . Apps . FromName ( ctx , "my-app" , & modal . AppFromNameParams { ... })
mc . Sandboxes . FromID ( ctx , "sb-123" )
Parameter structs renamed
All *Options types renamed to *Params and passed as pointers:
ClientOptions → ClientParams
LookupOptions → AppFromNameParams, FunctionFromNameParams, etc.
SandboxOptions → SandboxCreateParams
ExecOptions → SandboxExecParams
Field naming follows Go conventions
TokenId → TokenID
AppId → AppID
ServerUrl → ServerURL
See the migration guide for complete details.