Recipes API
Ellf’s recipes API is designed to make it easy to extend the functionality and develop custom workflows for your use cases. The recipes SDK package includes all Python utilities you need to implement a custom recipe, as well as helpers to configure the auto-generated UI forms and command-line interfaces that let you and your team start new tasks, actions and agents using your recipes.
Recipe decorator
The recipe decorator turns a Python function into a recipe and lets you provide basic information like titles and descriptions, as well as meta data used for the auto-generated form fields and command-line interface. Ellf provides three recipe decorators you can use to create and configure recipe functions:
@task_recipefor annotation tasks@action_recipefor actions that perform any logic@agent_recipefor autonomous agents
@task_recipe decorator
Recipe decorator for annotation tasks that start the Prodigy server and annotation app.
from typing import Literal
from ellf_recipes_sdk import task_recipe, props, TextProps, Dataset, Input
@task_recipe(
title="My Recipe",
description="This is a task recipe",
field_props={
"dataset": props.dataset_choice,
"input": TextProps(title="Input data")
},
)
def recipe(*, dataset: Dataset[Literal["text"]], input: Input):
stream = input.load()
return {
"dataset": dataset.name,
"stream": stream,
"view_id": "text",
}| Argument | Type | Description |
|---|---|---|
name | str | The recipe name. |
title | str | Display title of the recipe. |
description | str | Display description of the recipe. |
view_id | str | Prodigy interface ID to show in recipe preview in the app app. |
field_props | Dict[str, Props] | Props describing form fields for the UI, keyed by argument name. |
cli_names | Dict[str, str] | Mapping of nested field names to nicer, human-readable CLI argument names. |
module_name | str | If specified, overrides the module path used to register the recipe. Defaults to the __package__ of the function. |
| RETURNS | Callable | The decorated recipe function. |
@action_recipe decorator
Recipe decorator for actions that don’t start the annotation server and can execute any arbitrary Python logic like model training, data analysis, data conversion etc.
from ellf_recipes_sdk import action_recipe, TextProps, BoolProps, Input
@action_recipe(
title="My Recipe",
description="This is an action recipe",
field_props={
"input": TextProps(title="Input data"),
"verbose": BoolProps(title="Print examples")
},
)
def recipe(*, input: Input, verbose: bool = False):
stream = list(input.load())
print("Examples count:", len(stream))
if verbose:
print(stream)| Argument | Type | Description |
|---|---|---|
name | str | The recipe name. |
title | str | Display title of the recipe. |
description | str | Display description of the recipe. |
field_props | Dict[str, Props] | Props describing form fields for the UI, keyed by argument name. |
cli_names | Dict[str, str] | Mapping of nested field names to nicer, human-readable CLI argument names. |
module_name | str | If specified, overrides the module path used to register the recipe. Defaults to the __package__ of the function. |
| RETURNS | Callable | The decorated recipe function. |
@agent_recipe decorator
Recipe decorator for autonomous agents that run independently on the cluster and can be assigned to a task to create data and annotations. Agent recipes return an Annotator callable – a function that takes a task and config dict and returns an annotated task. The SDK handles server discovery, polling, and answer submission automatically.
from ellf_recipes_sdk import agent_recipe, Annotator, TextProps, FloatProps
from ellf_recipes_sdk import detect_task_type, format_prompt, parse_response
@agent_recipe(
title="My Annotation Agent",
description="Autonomous agent that annotates tasks using an LLM",
field_props={
"model": TextProps(title="Model name"),
"poll_interval": FloatProps(title="Poll interval (seconds)", min=0.1),
},
)
def my_agent(*, model: str = "my-model", poll_interval: float = 1.0) -> Annotator:
# Set up any resources (LLM client, spaCy model, etc.)
client = setup_llm(model)
async def annotate(task: dict, config: dict) -> dict:
task_type = detect_task_type(task)
prompt = format_prompt(task, task_type, config)
raw = await client.ask(prompt)
return parse_response(raw, task, task_type, model_name=model)
return annotate| Argument | Type | Description |
|---|---|---|
name | str | The recipe name. |
title | str | Display title of the recipe. |
description | str | Display description of the recipe. |
field_props | Dict[str, Props] | Props describing form fields for the UI, keyed by argument name. |
cli_names | Dict[str, str] | Mapping of nested field names to nicer, human-readable CLI argument names. |
module_name | str | If specified, overrides the module path used to register the recipe. Defaults to the __package__ of the function. |
| RETURNS | Callable | The decorated recipe function. |
Annotator type alias
The type expected as the return value of an @agent_recipe function. An Annotator is a callable that receives a task example dictionary and a config dictionary, and returns an annotated example dictionary. It can be either sync or async.
Annotator = Callable[
[dict[str, Any], dict[str, Any]], # example dict and config dict
dict[str, Any] | Awaitable[dict[str, Any]], # annotated task dict
]def annotator(eg: dict[str, Any], config: dict[str, Any]) -> dict[str, Any]:
annotated: dict[str, Any] = annotate(eg)
return annotatedThe annotated task dictionary must follow the same JSON format that the Prodigy annotation interface expects – the exact structure depends on the task type (e.g. spans for named entities or accept for multiple choice). It should also include an answer key with a value of "accept", "reject", or "ignore". You can optionally set _annotator_id and _session_id to identify the agent in the annotation data. If you’re using the built-in agent helpers, the response format is handled for you automatically.
Agent helpers functions
The SDK provides helper functions for building agent annotators. These handle the most common annotation patterns – detecting the task type from a Prodigy task dict, formatting an LLM prompt, and parsing the LLM’s JSON response back into the expected annotation format.
from ellf_recipes_sdk import detect_task_type, format_prompt, parse_response
task_type = detect_task_type(task) # e.g. "spans_manual"
prompt = format_prompt(task, task_type, config)
raw_response = await llm.ask(prompt) # your LLM call
result = parse_response(raw_response, task, task_type, model_name="my-model")| Function | Description |
|---|---|
detect_task_type | Infer the annotation task type from a task’s _view_id or keys. |
format_prompt | Build an LLM prompt for a given task, task type, and config. |
parse_response | Parse the LLM’s JSON response and merge the annotation decision into the task dict. |
Annotation task types
Annotation agents currently support the following task types, which determine how the agent should interpret the work and update the JSON.
| Name | Description | Annotation UI |
|---|---|---|
choice | Multiple-choice questions: select one or more options that apply. | choice |
ner_binary | Binary feedback about spans: accept or reject highlighted span(s) in context. | ner, spans |
spans_manual | Manual span annotation: add text span annotations for the given label(s). | ner_manual, spans_manual |
textcat_binary | Binary feedback about text category: accept or reject the given label for the whole text. | classification |
binary | Binary feedback: accept or reject the given example. | text, html |
Props
Props are Pydantic models that describe the properties of a recipe argument used for auto-generating the UI form fields and command line interface. They can include texts and descriptions that are displayed, optional UI widgets to use, as well as validations to check the input value against to display warnings and error messages. They can be defined as a dictionary keyed by argument name via the field_props argument of the recipe decorator.
Use the preview command when developing recipes
To try out different props and settings, you can use the ellf-dev preview command to show a live preview of the UI form in your browser. The preview live-reloads as you edit your code.
TextProps BaseModel
Props for a text field for string inputs.
from ellf_recipes_sdk import TextProps, task_recipe
custom_name = TextProps(
title="Custom name",
description="A custom name used in the recipe",
placeholder="Type name here..."
)
@task_recipe(title="My Recipe", field_props={"custom_name": custom_name})
def recipe(*, custom_name: str):
...| Argument | Type | Description |
|---|---|---|
title | str | Title of recipe argument. |
description | str | Description of recipe argument, used for help text. |
placeholder | str | Placeholder for input fields. |
optional_title | str | Text displayed with checkbox to toggle input if argument type is marked as Optional. |
pattern | str | Regex pattern for native browser input validation. |
validations | List[Validation] | One or more Validations to validate inputs and show errors or warnings. |
| RETURNS | BaseModel | The field props. |
BoolProps BaseModel
Props for a yes-or-no field and boolean inputs.
from ellf_recipes_sdk import BoolProps, task_recipe
update_model = BoolProps(
title="Update the model in the loop",
description="Check this to update the model from annotations",
)
@task_recipe(title="My Recipe", field_props={"update_model": update_model})
def recipe(*, update_model: bool):
...| Argument | Type | Description |
|---|---|---|
title | str | Title of recipe argument. |
description | str | Description of recipe argument, used for help text. |
widget | str | UI widget to use. "checkbox" or "toggle". |
| RETURNS | BaseModel | The field props. |
IntProps BaseModel
Props for a number field and integer inputs.
from ellf_recipes_sdk import IntProps
batch_size = IntProps(title="Batch size", min=24, step=8)
@task_recipe(title="My Recipe", field_props={"batch_size": batch_size})
def recipe(*, batch_size: int):
...| Argument | Type | Description |
|---|---|---|
title | str | Title of recipe argument. |
description | str | Description of recipe argument, used for help text. |
optional_title | str | Text displayed with checkbox to toggle input if argument type is marked as Optional. |
min | int | Minimum value of number. |
max | int | Maximum value of number. |
step | int | Step by which to increment number in field controls. Defaults to 1. |
widget | str | UI widget to use. "number" or "range". |
validations | List[Validation] | One or more Validations to validate inputs and show errors or warnings. |
| RETURNS | BaseModel | The field props. |
FloatProps BaseModel
Props for a number field and float inputs.
from ellf_recipes_sdk import FloatProps, task_recipe
learn_rate = FloatProps(title="Learning Rate", min=0.001, step=0.001)
@task_recipe(title="My Recipe", field_props={"learn_rate": learn_rate})
def recipe(*, learn_rate: float):
...| Argument | Type | Description |
|---|---|---|
title | str | Title of recipe argument. |
description | str | Description of recipe argument, used for help text. |
optional_title | str | Text displayed with checkbox to toggle input if argument type is marked as Optional. |
min | float | Minimum value of number. |
max | float | Maximum value of number. |
step | int | Step by which to increment number in field controls. Defaults to 1. |
widget | str | UI widget to use. "number" or "range". |
validations | List[Validation] | One or more Validations to validate inputs and show errors or warnings. |
| RETURNS | BaseModel | The field props. |
ListProps BaseModel
Props for a list field and inputs of type List.
from ellf_recipes_sdk import ListProps, task_recipe
labels = ListProps(
title="Labels",
placeholder="Type labels here...",
min=1,
)
@task_recipe(title="My Recipe", field_props={"labels": labels})
def recipe(*, labels: List[str]):
...| Argument | Type | Description |
|---|---|---|
title | str | Title of recipe argument. |
description | str | Description of recipe argument, used for help text. |
placeholder | str | Placeholder for input fields. |
optional_title | str | Text displayed with checkbox to toggle input if argument type is marked as Optional. |
min | int | Minimum number of items in the list. |
max | int | Maximum number of items in the list. |
validations | List[Validation] | One or more Validations to validate inputs and show errors or warnings. |
| RETURNS | BaseModel | The field props. |
ChoiceProps BaseModel
Props for a selection field with pre-defined options and inputs of type Union or a Literal of multiple options.
from ellf_recipes_sdk import ChoiceProps, Props, task_recipe
goal = ChoiceProps(
title="Data collection goal",
choice={
"nooverlap": Props(title="Annotate all examples once"),
"overlap": Props(title="Annotate with overlap"),
},
)
@task_recipe(title="My Recipe", field_props={"goal": goal})
def recipe(*, goal: Literal["nooverlap", "overlap"]):
...| Argument | Type | Description |
|---|---|---|
title | str | Title of recipe argument. |
description | str | Description of recipe argument, used for help text. |
optional_title | str | Text displayed with checkbox to toggle input if argument type is marked as Optional. |
choice | Dict[str, Props] | Optional props for the individual choices. If the choices are custom types, i.e. dataclasses and already define props, those will be used. |
widget | str | UI widget to use. "select" (dropdown) or "radio" (list of options). |
validations | List[Validation] | One or more Validations to validate inputs and show errors or warnings. |
| RETURNS | BaseModel | The field props. |
Props BaseModel
Base class that all specific props types inherit from and that can be used for all other arguments.
| Argument | Type | Description |
|---|---|---|
title | str | Title of recipe argument. |
description | str | Description of recipe argument, used for help text. |
placeholder | str | Placeholder for input fields. |
optional_title | str | Text displayed with checkbox to toggle input if argument type is marked as Optional. |
pattern | str | Regex pattern for native browser input validation. |
min | int | Minimum value of number or list items. |
max | int | Maximum value of number or list items. |
step | int | Step by which to increment number in field controls. Defaults to 1. |
choice | Dict[str, Props] | Optional props choices in choice props. |
widget | str | UI widget to use, depending on the field. |
validations | List[Validation] | One or more Validations to validate inputs and show errors or warnings. |
| RETURNS | BaseModel | The field props. |
Validation BaseModel
Validations are used in the UI form when creating and configuring a task or action. They’re a powerful way to define custom constraints for the expected input and show messages to the user, including errors that prevent the form from being submitted, as well as warnings and info messages to help enforce best practices. Each prop can define one or more validations in order that are interpreted based on the field type, e.g. comparing the length of a list, a string or a number. See the recipe development guide for more details and examples.
validations = [
Validation(
op="re",
value="^[\\w-]+$",
message="It can contain only numbers, letters, dashes '-' and underscores '_'",
level="error",
),
Validation(
op="gt",
value=20,
message="It's recommended to use a shorter name (20 characters or less)",
level="warning",
)
]| Argument | Type | Description |
|---|---|---|
op | str | Validation operator. Either "ge" (greater or equal), "gt" (greater than), "le" (lower or equal), "lt" (lower than), "eq" (equal), "ne" (not equal) or "re" (regular expression). |
value | Union[int, float, str, bool] | Validation value, depending on props type and operator, e.g. a number, text length or list length to compare input to, or a regular expression to match against. |
message | str | Message to display if validation matches. |
level | str | Validation level. Either "error", "warning", "info" or "success". |
| RETURNS | BaseModel | The field validation. |
Pre-defined props
Some arguments are very common across recipes, and so are their props. Ellf’s recipe development SDK includes several pre-configured props as variables that you can import and use, so you don’t have to repeat titles, help texts and field settings.
from typing import List
from ellf_recipes_sdk import props, Dataset, InputDataset, Lang
@task_recipe(
"my-recipe",
field_props={
"dataset": props.dataset_new,
"input_dataset": props.dataset_existing,
"other_dataset": props.dataset_choice,
"label": props.label,
"lang": props.lang,
}
)
def recipe(
*,
dataset: Dataset,
input_data: InputDataset,
other_dataset: Dataset,
label: List[str],
lang: Lang
):
...| Name | Props Type | Argument Type | Description |
|---|---|---|---|
dataset_new | TextProps | Dataset | Props for a new dataset that should be created by the recipe. Renders a text input for the dataset name. |
dataset_existing | Props | InputDataset | Props for an existing dataset. Renders a dropdown to select the dataset. |
dataset_choice | Props | Dataset | Props for a choice of new dataset of existing dataset. Renders a selection field between the two and the respective input after selection. |
label | ListProps | List[str] | Props for a list of comma-separated labels. Renders an input field for lists. |
lang | ChoiceProps | Lang | Props for language supported by spaCy. Renders a dropdown with human-readable language names. |
Types and dataclasses
Ellf includes a range of pre-defined argument types, usually dataclasses, for common recipe arguments. The recipe will then receive an instance of the dataclass. Dataclasses can also define their own methods, e.g. a load method to load a given asset or dataset.
Dataset | A new dataset created by the recipe. |
InputDataset | An existing dataset used as input data. |
Asset | Base class for all assets, not typically used directly. |
Input | Asset type for loadable input data. |
Patterns | Asset type for JSON-formatted match patterns. |
Model | Asset type for loadable models. |
BlankModel | A blank spaCy nlp object, e.g. for tokenization. |
UseModel | Pre-defined custom type for using and updating model in the loop. |
Lang | Enum of all available spaCy languages. |
Secret | API keys and other credentials added to Ellf. |
@ellf_type | Decorator for defining custom types as dataclasses. |
Dataset dataclass
Type of a new dataset to create by the recipe. It’s a generic type that allows specifying the dataset kind as a parameter, e.g. Dataset[Literal["text"]] for datasets of kind "text". Specifying a kind will also limit the datasets that can be selected in the UI. When used in a recipe, the function will receive an instance of the dataclass.
from typing import Literal
from ellf_recipes_sdk import Dataset, task_recipe
@task_recipe(title="My Recipe")
def recipe(*, dataset: Dataset[Literal["text"]]):
return {"dataset": dataset.name, ...}| Field | Type | Description |
|---|---|---|
id | UUID | The dataset ID. |
name | str | The dataset name. |
kind | str | Kind of the dataset, used to filter in recipes to only allow specific types. |
broker_id | UUID | The ID of the cluster the dataset is associated with. |
InputDataset dataclass
Type of an existing dataset that’s required to already be in the database, e.g. for datasets used as input data. It’s a generic type that allows specifying the dataset kind as a parameter, e.g. InputDataset[Literal["text"]] for datasets of kind "text". Specifying a kind will also limit the datasets that can be selected in the UI.
from typing import Literal
from ellf_recipes_sdk import InputDataset, task_recipe
@task_recipe(title="My Recipe")
def recipe(*, input_dataset: InputDataset[Literal["text"]]):
stream = input_dataset.load()InputDataset.load method
Load the examples from the input dataset. It takes the same keyword arguments as Prodigy’s get_stream and returns a stream of examples.
| Argument | Type | Description |
|---|---|---|
**kwargs | Optional keyword arguments passed to Prodigy’s get_stream. | |
| RETURNS | Iterator[dict] | The stream of examples loaded from the dataset. |
InputDataset.export method
Export the examples from the dataset as JSONL (newline-delimited JSON).
| Argument | Type | Description |
|---|---|---|
path | Path | Path to save examples to. |
Asset dataclass
Base class for asset. It’s a generic type that allows specifying the asset kind as a parameter, e.g. Asset[Literal["input"]] for Input. It’s typically not used directly and subclassed for specific asset types (see below). When used in a recipe, the function will receive an instance of the dataclass. See the docs on custom assets for details on how to create your own subclasses.
| Field | Type | Description |
|---|---|---|
id | UUID | The asset ID. |
name | str | The asset name. |
version | str | The asset version. |
kind | str | Kind of the asset. "input", "model", "patterns" or custom. |
path | str | The asset path, e.g. a directory in the bucket of your cluster, or a remote path. |
meta | dict | Asset meta information set in ellf assets create. |
broker_id | UUID | The ID of the cluster the asset is associated with. |
Input dataclass
Type of an asset used as input for a recipe, e.g. a text source. Subclass of Asset[Literal["input"]].
from ellf_recipes_sdk import Input, task_recipe
@task_recipe(title="My Recipe")
def recipe(*, input_data: Input):
stream = input_data.load()Input.load method
Load the examples from the input asset. It takes the same keyword arguments as Prodigy’s get_stream and returns a stream of examples.
| Argument | Type | Description |
|---|---|---|
**kwargs | Optional keyword arguments passed to Prodigy’s get_stream. | |
| RETURNS | Iterator[dict] | The stream of examples loaded from the asset. |
Input.create classmethod
Register a new input asset record with Ellf. Note that this only creates the record – you need to write the actual files to your cluster’s storage bucket first, e.g. using cloudpathlib.AnyPath. See creating assets in recipes for a full example.
from ellf_recipes_sdk import Input, action_recipe
@action_recipe(title="My Recipe")
def recipe():
asset = Input.create(name="My asset", path="{__bucket__}/my_asset", loader="jsonl")| Field | Type | Description |
|---|---|---|
name | str | The asset name. |
version | str | The asset version. |
path | str | The asset path, e.g. a directory in the bucket of your cluster, or a remote path. |
loader | str | ID of loader to use for the asset. |
meta | dict | Additional asset meta information. |
| RETURNS | Input | The newly created input asset record. |
Input.update method
Update an existing input asset with a new version. By default, the original asset version will be incremented as a patch, e.g. 1.2.3 becomes 1.2.4.
from ellf_recipes_sdk import Input, action_recipe
@action_recipe(title="My Recipe")
def recipe(input: Input):
input.update(path="{__bucket__}/my_updated_asset")| Field | Type | Description |
|---|---|---|
path | str | The asset path, e.g. a directory in the bucket of your cluster, or a remote path. |
version | str | Optional new asset version. |
| RETURNS | Input | The updated input asset record. |
Patterns dataclass
Type of a patterns file, a kind of asset, for recipes that use pattern matching. When loaded, it creates a PatternMatcher instance that you can use on your stream to automatically add annotations from patterns. Subclass of Asset[Literal["patterns"]].
from ellf_recipes_sdk import Model, Input, Patterns, task_recipe
@task_recipe(title="My Recipe")
def recipe(*, spacy_model: Model, input_data: Input, patterns: Patterns):
nlp = spacy_model.load()
stream = input_data.load()
matcher = patterns.load(nlp=nlp, label="PERSON")
stream = (eg for _, eg in matcher(stream))Patterns.load method
Load the patterns and initialize a PatternMatcher that can be used by the recipe. This method takes the same arguments as Prodigy’s PatternMatcher to configure how the patterns should be applied.
| Argument | Type | Description |
|---|---|---|
nlp | Language | The spaCy language class to use for the matchers and to process text. |
label | List[str] | Only add patterns if their labels are part of this list. If None (default), all labels are used. |
label_span | bool | Whether to add a "label" to the matched span that’s highlighted. For example, if you use the matcher for NER, you typically want to add a label to the span but not the whole task. |
label_task | bool | Whether to add a "label" to the top-level task if a match for that label was found. For example, if you use the matcher for text classification, you typically want to add a label to the whole task. |
combine_matches | bool | Whether to show all matches in one task. If False, the matcher will output one task for each match and duplicate tasks if necessary. |
all_examples | bool | If True, all examples are returned, even if they don’t contain matches. If False (default), only examples with at least one match are returned. |
allow_overlap | bool | Whether the matcher is allowed to produce overlapping spans, e.g. if used with spans or spans_manual. |
| RETURNS | PatternMatcher | The initialized pattern matcher using the patterns. |
Model dataclass
Type of a spaCy model, a kind of asset uploaded to the cluster. When loaded, it returns the initialized nlp object. Subclass of Asset[Literal["model"]].
from ellf_recipes_sdk import Model, task_recipe
@task_recipe(title="My Recipe")
def recipe(*, spacy_model: Model):
nlp = spacy_model.load()Model.load method
Load a spaCy model and initialize the nlp object. Before loading, the model will be downloaded to the worker on your cluster that’s executing the recipe.
| Argument | Type | Description |
|---|---|---|
download_to | Optional[Path] | Optional alternative path to download model to. If not set, a temporary directory is used. |
| RETURNS | Language | The loaded model, i.e. the nlp object. |
BlankModel dataclass
Create a blank nlp object for one of the available spaCy languages for tokenization or training a new pipeline. The language to use is a field of the type and can be set in the UI or on the CLI when a task or action is created from the recipe.
from ellf_recipes_sdk import BlankModel, task_recipe
@task_recipe(title="My Recipe")
def recipe(*, spacy_model: BlankModel):
nlp = spacy_model.load()
print(f"Created blank model for {spacy_model.lang}")| Field | Type | Description |
|---|---|---|
lang | Lang | The language to use, e.g. Lang.de. Defaults to Lang.en. |
BlankModel.load method
Initialize a blank nlp object.
| Field | Type | Description |
|---|---|---|
| RETURNS | Language | The blank model, i.e. the nlp object. |
UseModel dataclass
Pre-defined custom type for recipes that use a model to pre-annotate data. Combines the model name and a boolean setting whether it should be updated in the loop (which needs to be implemented in the recipe). Can also be used as part of a Union type with BlankModel so the user can choose between a pretrained pipeline or a blank model.
from typing import Union
from ellf_recipes_sdk import UseModel, BlankModel, task_recipe
@task_recipe(title="My Recipe")
def recipe(*, spacy_model: Union[UseModel, BlankModel]):
nlp = spacy_model.load()
if isinstance(spacy_model, UseModel) and spacy_model.update:
# Implement logic to update the model in the loop
...| Field | Type | Description |
|---|---|---|
name | Model | The model to load. |
update | bool | Setting that can be used to update model in the loop. |
Lang enum
Enum of all available spaCy languages that can be initialized with spacy.blank, e.g. for tokenization or training a new pipeline.
from ellf_recipes_sdk import Lang, task_recipe
import spacy
@task_recipe(title="My Recipe")
def recipe(*, lang: Lang = Lang.en):
nlp = spacy.blank(lang)Secret dataclass
Secrets are pointers to API keys or other credentials and let you securely manage access across your organization. If your recipe needs to connect to an API or authenticate with a service, you shouldn’t ever have your user provide their credentials in the web form or CLI. Instead, you can use the Secret type so you’ll be able to select an existing secret, which is then passed to your recipe function.
from ellf_recipes_sdk import agent_recipe, Secret
@agent_recipe(title="My Recipe")
def recipe(*, api_key: Secret):
gemini_key = api_key.value()
llm = Gemini(api_key=gemini_key, model_name="gemini-2.0-flash")| Field | Type | Description |
|---|---|---|
id | UUID | The secret ID. |
name | str | The secret name. |
broker_id | UUID | The ID of the cluster the secret is associated with. |
Secret.value method
Get the plain-text value of a secret. This is what should be passed to API calls and other libraries that require keys to authenticate, for example in agent recipes. The value is resolved automatically based on the recipe parameter the secret was bound to – you don’t need to know the internal storage key.
| Argument | Type | Description |
|---|---|---|
| RETURNS | str | The secret value. |
@ellf_type decorator
Decorator to register dataclasses as custom types. Dataclasses can define one or more custom subfields and an instance of the dataclass will be passed to the recipe function if it’s used as a type annotation. Custom types can also be used as part of a union. The metadata defined in the decorator is propagated and merged to child classes that are also annotated with @ellf_type. See the recipe development guide and custom assets for more details and examples.
Using the dataclass decorator
While it’s not strictly required, the @ellf_type decorator should always be used together and on top of the @dataclass decorator to improve type checking support in your editor and static type checker.
from typing import Literal, Optional
from dataclasses import dataclass
from ellf_recipes_sdk import ellf_type, IntProps
@ellf_type(
"workflow-settings",
title="Customize annotation workflow",
field_props={"annotations_per_task": IntProps(optional_title="Configure annotations per task")}
)
@dataclass
class WorkflowSettings:
feed_overlap: Literal["nooverlap", "overlap"] = "nooverlap"
annotations_per_task: Optional[int] = None
allow_work_stealing: bool = True
instructions: str = ""| Argument | Type | Description |
|---|---|---|
type | str | If provided this will be the type in the schema, instead of the class name. Useful for having shorter names and also for having a whole hierarchy with the same type, e.g. Dataset and Asset classes. |
title | str | Custom type title. Will be merged to props afterwards. |
description | str | Custom type description. Will be merged to props afterwards. |
props | Props | Additional type props that will be used whenever this type is used so you don’t have to repeat it everywhere, but you can override it. |
field_props | Dict[str, Props] | Props for the individual fields of the custom type dataclass, keyed by field name. |
exclude | Set[str] | Field names to exclude from the schema. |
| RETURNS | dataclass | The custom type dataclass. |