Chalk home page
  1. Tutorial
  2. Inference

If you want to skip ahead, you can find the full source code for this tutorial on GitHub.

Now that we’ve written some features and resolvers and deployed them to Chalk, we’re ready to integrate Chalk into our production decisioning systems.

CLI Query

As a sanity check, it can be helpful to use the Chalk CLI to query a well-known input and ensure that we get the expected output.

We can use the chalk query command, passing in the id of a user, and the names of the features we want to resolve:

$ chalk query --in  \
              --out  \
              --out \
              --out user.account.balance
Results             "John Doe"
email                 ""
user.account.balance  2032.91

API Client Query

Once we’re satisfied that our features and resolvers are working as expected, we can use a client library to query Chalk from our application.

In this first example, we’ll use the ChalkClient in the chalkpy package to query Chalk from our application:

from src.models import User
from chalk.client import ChalkClient

# Create a new Chalk client. By default, this will
# pick up the login credentials generated after running
# `chalk login`.
client = ChalkClient()


We use the same feature definitions for querying our data as we used for defining our features and resolvers.

Chalk has API client libraries in several languages, including Python, Go, Typescript, and Elixir.

Code Generation (Optional)

All API clients can operate on the string names of features. However, in a production system, you may have many hundreds or thousands of features, and want to avoid hard-coding the names of each feature in your code.

To help with this, Chalk can codegen a library of strongly-typed feature names for you.

For example, say the service that calls into Chalk is written in Go. We can generate a Go library of feature names with the following command:

$ chalk codegen go --out ./clients/go/client.go --package=client
✓ Found resolvers
✓    Wrote features to file './clients/go/client.go'
✓    Please do not change the generated code.

This generates a file clients/go/client.go that looks like this:

package client

 Code generated by Chalk. DO NOT EDIT.
 > chalk codegen go --out ./clients/go/client.go --package client

import (

var InitFeaturesErr error

type Account struct {
	Id *int64
	Title *string
	UserId *int64
	Balance *float64
	User *User
	UpdatedAt *time.Time

type User struct {
	Id *int64
	Name *string
	Email *string
	Account *Account
	AccountNameMatch *float64
	FicoScore *int64
	CreditScoreTags *[]any

var Features struct {
	Account *Account
	User *User

func init() {
	InitFeaturesErr = chalk.InitFeatures(&Features)

We can then use this library to query Chalk:

import (

// Create a new Chalk client.
client := chalk.NewClient()

// Create an empty struct to hold the results.
user := User{}

// Query Chalk, and add the results to the struct.
_, err = client.OnlineQuery(
        WithInput(Features.User.Id, 1234).

// Now, you can access the properties of the
// user for which there was a matching `output`.

If your calling service is written in Python, but you don’t want to take a dependency on the repository that contains your Chalk features, you can generate your Python features into a separate repository:

$ chalk codegen python --out ./clients/python/

You can see the generated code in clients/python/

If you are generating Python into a subdirectory of your Chalk project, be sure to add an entry to your .chalkignore containing the directory of your generated code (in the above example, clients/). Otherwise, Chalk will find duplicate definitions of your features.