Chalk home page
  1. Resolvers
  2. Tags

Tags allow you to scope requests within an environment. Both tags and environment need to match for a resolver to be a candidate to execute.

You might consider using tags, for example, to change out whether you want to use a sandbox environment for a vendor, or to bypass the vendor and return constant values in a staging environment.

Specifying tags

Tags can be either a string value, or a key-value pair. As a best practice (and fitting with recommendations from other services like Datadog), we recommend using key-value pairs, but the choice is yours.

There are two ways to specify tags on resolvers:

  • “key” - As a single scalar string.
  • “key:value” - As a string value representing a key-value pair.

Resolvers take one or many tags, all of which need to match for the resolver to run. For example, you may want to test with a sandboxed vendor, and also be able to set a constant value for a particular feature. For instructions on how to set tags on SQL file resolvers, see the SQL file resolvers docs

@online(tags=["api:mock", "fraud"])
def simulate_fraud(id: -> User.fraud_score:
    return 100

def simulate_no_fraud(id: -> User.fraud_score:
    return 10

def sandbox_score(
) -> User.fraud_score:
    return sandbox.fraud_score(name, email).score

def real_score(
) -> Features[User.fraud_score, User.fraud_tags]:
    r = prod.fraud_score(name, email).score
    return User(fraud_score=r.score, fraud_tags=r.tags)

In the above example, the resolver that is chosen to compute the User.fraud_score feature will depend on the tags provided at query time. The table below shows which resolver will be chosen for a given set of tags.

Query tagsResolver
[api:mock, fraud] simulate_fraud
api:mock simulate_no_fraud
api:sandbox sandbox_score
<otherwise> real_score

Note that these resolvers don’t need to take the same set of inputs, and don’t need to return the same types.

When tagged resolvers run

Like Environments, tags control when resolvers run based on the Online Context or Training Context matching the tags provided to the resolver decorator. Resolvers optionally take a keyword argument named tags that can take one of three types:

  • Unassigned (default) - The resolver will be a candidate to run for every set of tags.
  • String value - The resolver will run only if this tag is provided.
  • List of strings - The resolver will run only if all of the specified tags match.

If your resolver is tagged only by a key (not a key-value pair), and the request context contains a key-value pair such that the resolver’s tag (a key only) matches they key of a key-value pair in the context, the resolver will be eligible to run. For example:

Resolver TagRequest ContextMatches?
api api Yes
api api:live Yes
[api:live, mock-phone] [api:live, mock-phone] Yes
[api:live, mock-phone] api:live No
api:live api No
api:fixture api:live No


Frequently, you’ll want to combine tags and Environments, as below. This span uses a constant value in staging when the tag api takes the value fixture, uses the sandboxed fraud vendor in staging when the tag api takes the value live, and uses the production fraud vendor in production.

@online(environment="staging", tags="api:fixture")
def fraud_score_fixture(email: -> UserFeatures.fraud_score:
    if email == "":
        return 100
    return 50

@online(environment="staging", tags="api:live")
def fraud_score_sandbox(email: -> UserFeatures.fraud_score:
    return api_vendor_sandbox.fraud_score(email, profile="dev")

def fraud_score_prod(email: -> UserFeatures.fraud_score:
    return api_vendor_live.fraud_score(email)