Blocks are the units of work that comprise a worklet.
Blocks are the units of work that comprise a worklet. To create a block, click "Add block" in a worklet graph and select the type of block that you want to add.


Baseten allows you to write your own Python code as part of your worklet. Simply add a Code block to your worklet and select the desired function from a file.
A code block
Code blocks require a function with the following signature, selected from the appropriate file.
def func(block_input, env, context):
The three arguments are all optional, but they are positional, so you can't have env without block_input or context without both block_input and env. Because the arguments are positional, you can call them whatever you want, but we recommend sticking with the standard parameter names. Valid function signatures:
def func():
def func(block_input):
def func(block_input, env):
def func(block_input, env, context):
def func(predictions, env, context): # Meaningful name for block_input
def func(apples, oranges, grapefruit): # Valid, but not recommended
Let's examine the arguments individually.


This is the input to the block. If this block is the first in the worklet, then block_input is what the worklet was called with. Otherwise block_input is the return value of the previous block in the worklet.


Exclusively relying on block input/output for the execution of the worklet would cause headaches. What if the final block needs to access the first block's input? Would you have to ensure that the input is passed along all the way to the end? No.
That's where env comes in. It's an empty dictionary to which you can add key/value pairs (again, JSON-serializable values only). env is persisted through the worklet execution, which means that after a block modifies it, all subsequent blocks have access to that data.


While block_input is limited in scope to a single block and env is limited to a single worklet, context infuses your function with every available data source. context provides contextual information as well as variety of ways of invoking many Baseten functionalities:
  1. 1.
    Access to external data connections (e.g. Snowflake, Redis, and PostgreSQL)
  2. 2.
    ORM access to user-defined data tables
  3. 3.
    Access to secrets
  4. 4.
    Access to user information like user ID and username
Visit those pages to learn how to use the context parameter for specific use cases.

Return value

It's worth repeating that Code blocks must explicitly return a JSON-serializable value to use as input for the next block, unless the Code block in question is the last block in a worklet. Even in this case, we recommend returning JSON in case the worklet is ever called from another worklet.
If your function is only called for its side effects, simply end with return block_input to pass along the block's input to the next block in the worklet.


A Model block is the heart of any ML-powered worklet. This block invokes a selected model and returns its output.
A model block
While the model doesn't have access to env or context, the output of the previous block becomes the model's input. As such, make sure to pass along an input of the correct type. For example, if the model expects a list or numpy array, the previous block should return this type.
In your model blocks, you can set a model's version. Like all changes to worklets, changing a model version is environment-specific for users in workspaces with the draft environment feature. Setting the model version to primary will keep your worklet up-to-date as you publish new model versions, but specifying a version lets you roll out new model versions in sync with application changes that support the new version.


A Query block lets you access queries directly in worklets.
A query block
The query block, like all other blocks, takes a JSON dictionary as input. For queries that do not require input, this can be an empty dictionary. But in some cases, we need to pass inputs into a query. For example:
Round(friendly_score, 2) AS "Friendly score",
Round(dangerous_score, 2) AS "Dangerous score",
Round(not_feline_score, 2) AS "Not feline score"
friendly_score < {{upper_limit}}
AND friendly_score > {{lower_limit}}
AND friendly_score != 1
AND dangerous_score != 1
OR (
not_feline_score > friendly_score
AND not_feline_score > dangerous_score
In this case, invoking the query block would require passing in:
"upper_limit": 0.6,
"lower_limit": 0.4
The query block outputs a dictionary with the key results and a list of query results. For example, a query that returns the following tabular output:
question | answer
"What is 1 + 1" | 2
"What is 7 - 2" | 5
Would return the following JSON when run as a worklet block:
"results": [
"question": "what is 1 + 1",
"answer": 2
"question": "what is 7 - 2",
"answer": 5


Decision blocks are very similar to Code blocks in that you write custom Python code with access to the same block_input, env, context args. However, Decision blocks' output must be a boolean, which will determine which of its two child blocks should be called next.
A decision block
If the decision block returns True (or a truthy value), the "then" path will be executed. If it returns False (or equivalent), the "else" path will be executed.
Since a block's output becomes the subsequent block's input, you can imagine that the boolean result of the Decision block will become the input to its subsequent block. That would be somewhat useless, so we made an exception: The input to the Decision block becomes the input to the subsequent block.
While block_inputand env are available arguments for a Decision block's function, they are considered read-only. Decision blocks should solely return a boolean value, not have any side effects. Any changes made to the input or environment will not be available in subsequent blocks.


Worklets, like functions, are composable. With a worklet block, you can call another worklet from your current worklet. This does not result in a new API request or worklet invocation, and env persists in the called worklet. This block returns the result of the called worklet, so be sure to format it as a valid input for the next block.
A worklet block
If you don't enjoy recursion, you can skip this paragraph and still be a fully capable Baseten user. A worklet can call itself, opening the possibility of recursive worklets. Also, worklet A can call worklet B, which in turn calls worklet A. Such complexities are rarely the best way to solve problems, but we have left the capability in the platform to maximize developer freedom and flexibility. The runtime will error out at an unsustainable recursion depth (think hundreds of recursive calls), so don't go too wild.


To send a Slack message from a worklet:
  1. 1.
    In Slack, create a webhook.
  2. 2.
    Paste the webhook into the appropriate field.
  3. 3.
    Write your message! To include the value of block_input in your message, use a single empty pair of curly braces {}.
When you run the worklet, the Slack message will be sent!
The output of the Slack block will be {'message_sent': 'Your message here'}, so if you have any blocks set to run after the Slack block make sure that any necessary variables are stored in env.
A Slack block
Slack is our first of many planned integrations. If there is an API that you would like a similar integration for, please let us know.