Skip to content

Utilities API

Helpers for prompt construction, JSON-schema and grammar generation, LLM-facing documentation, chat persistence and logging.

Message Template

Fills {placeholder} fields in a prompt string. Used by pipeline steps to turn a prompt_template into the actual prompt.

from ToolAgents.utilities.message_template import MessageTemplate

template = MessageTemplate.from_string("Hello {name}, welcome to {place}.")
template.generate_message_content(name="Max", place="Königswinter")

Placeholder paths

A placeholder may address a nested value with /:

template = MessageTemplate.from_string("Revise {outputs/draft} for {inputs/audience}")
template.generate_message_content(results)

This works against any nested mapping, and against a PipelineResults object, which resolves the first segment as a section name.

Pass the mapping; do not unpack it

Path resolution needs the structure intact. generate_message_content(results) resolves {outputs/draft}; generate_message_content(**results) flattens the mapping first and the path can no longer resolve. Mixing template_fields with keyword arguments flattens too.

Unmatched placeholders

  • A bare name with no matching field is blanked, and a line containing nothing else is dropped (remove_empty_template_field=True, the default). This is deliberate for optional sections of a prompt, but it means a typo in a bare placeholder fails silently.
  • A path that does not resolve is left verbatim, so text that was always literal — {a/b} — survives, and a mistyped path stays visible.
  • A field whose value is None counts as absent and is blanked, rather than rendering the literal string "None".

Set remove_empty_template_field=False to leave every unmatched placeholder in the output.

Behaviour change in 0.3.3

Two things about placeholder handling changed in 0.3.3, when path support was added. Neither breaks a template that was previously working, but both are worth knowing before upgrading.

Placeholder names may now contain /. The pattern widened from \{(\w+)\} to \{([\w/]+)\}. Text that was always literal is unaffected: a placeholder containing / that does not resolve is left exactly as written, so {a/b} in an existing prompt still renders as {a/b}.

A None value now counts as absent. Previously a field set to None rendered the literal string "None" into the prompt; it is now blanked like any other missing field. This is the one case where output changes for an unmodified template. If you were relying on the old behaviour, pass the string yourself:

template.generate_message_content(value="None" if value is None else value)

MessageTemplate

MessageTemplate(template_file=None, template_string=None)

A prompt template with {placeholder} fields.

Build one with :meth:from_string or :meth:from_file, then fill it with :meth:generate_message_content. A placeholder may address a nested value with /, as in {outputs/draft}.

Attributes:

Name Type Description
template str

The template string containing placeholders.

Initialize a PromptTemplate instance.

Parameters:

Name Type Description Default
template_file str

The path to a file containing the template.

None
template_string str

The template string.

None

from_string classmethod

from_string(template_string) -> MessageTemplate

Create a PromptTemplate instance from a string.

Parameters:

Name Type Description Default
template_string str

The template string.

required

Returns:

Name Type Description
PromptTemplate MessageTemplate

Created PromptTemplate instance.

from_file classmethod

from_file(template_file) -> MessageTemplate

Create a PromptTemplate instance from a file.

Parameters:

Name Type Description Default
template_file str

The path to a file containing the template.

required

Returns:

Name Type Description
PromptTemplate MessageTemplate

Created PromptTemplate instance.

generate_message_content

generate_message_content(
    template_fields: Dict[str, Any] = None,
    remove_empty_template_field: bool = True,
    **kwargs: Any
) -> str

Generate a prompt by replacing placeholders in the template with values.

Parameters:

Name Type Description Default
template_fields Dict[str, Any]

The template fields as a dictionary.

None
remove_empty_template_field bool

If True, removes lines with empty placeholders.

True
**kwargs Any

Additional keyword arguments to be used as template fields.

{}

Returns:

Name Type Description
str str

The generated prompt.

resolve_template_path

resolve_template_path(
    fields: Mapping, path: str
) -> tuple[bool, Any]

Resolve a possibly-sectioned path against a mapping.

Returns (found, value). A mapping that knows its own sections — such as PipelineResults — resolves the path itself; anything else is walked as nested mappings, so a plain dict of dicts works too.

ChatFormatter

ChatFormatter(template, role_names: Dict[str, str] = None)

Prompt Builder

A fluent builder for multi-part prompts.

PromptBuilder

PromptBuilder()

PromptPart

Bases: ABC

PromptVar

PromptVar(var=None)

Bases: PromptPart

PromptLine

PromptLine()

Bases: PromptPart

JSON Schema Generation

custom_json_schema is the entry point: it produces a fully $ref-resolved schema for a Pydantic model, which is what tool definitions are built from.

custom_json_schema

custom_json_schema(model: Type[BaseModel]) -> dict

Generate a custom JSON schema for a given Pydantic model. All $refs are resolved inline for a fully expanded schema.

Parameters:

Name Type Description Default
model Type[BaseModel]

The Pydantic BaseModel class

required

Returns:

Type Description
dict

A fully resolved JSON schema dict

get_tools_schema

get_tools_schema(tool_registry: Any) -> Dict[str, Any]

Generate a combined schema for all tools in a tool registry.

Parameters:

Name Type Description Default
tool_registry Any

Object with a 'tools' dict attribute

required

Returns:

Type Description
Dict[str, Any]

Dict[str, Any]: Combined JSON schema for all tools as an array

refine_schema

refine_schema(schema: dict, model: Type[BaseModel]) -> dict

Refine the generated schema based on the model's annotations and field details. Recursively handles Enums, Unions, lists/sets, dictionaries, and nested Pydantic models.

Parameters:

Name Type Description Default
schema dict

The base schema dict from model.model_json_schema()

required
model Type[BaseModel]

The Pydantic model class

required

Returns:

Type Description
dict

Refined schema dict with all $refs resolved

insert_additional_fields

insert_additional_fields(
    schema: dict,
    additional_fields: List[AdditionalSchemaField],
) -> dict

Insert additional fields into the schema's properties. Fields with position 'before' will be added at the start, and those with 'after' will be appended at the end.

Parameters:

Name Type Description Default
schema dict

The schema dict to modify

required
additional_fields List[AdditionalSchemaField]

List of additional fields to insert

required

Returns:

Type Description
dict

Modified schema dict

AdditionalSchemaField

Bases: BaseModel

Represents an additional schema field.

AdditionalFieldPosition

Bases: Enum

GBNF Grammar Generation

Constrained-decoding grammars for local inference backends such as llama.cpp, generated from Pydantic models.

generate_gbnf_grammar_and_documentation

generate_gbnf_grammar_and_documentation(
    pydantic_model_list: List[Type[BaseModel]],
    outer_object_name: str | None = None,
    outer_object_content: str | None = None,
    model_prefix: str = "Output Model",
    fields_prefix: str = "Output Fields",
    list_of_outputs: bool = False,
    documentation_with_field_description=True,
    add_inner_thoughts: bool = False,
    allow_only_inner_thoughts: bool = False,
    inner_thoughts_field_name: str = "thoughts_and_reasoning",
    add_request_heartbeat: bool = False,
    request_heartbeat_field_name: str = "request_heartbeat",
    request_heartbeat_models: List[str] = None,
) -> Tuple[str, str]

Generate GBNF grammar and documentation for a list of Pydantic models.

Parameters:

Name Type Description Default
pydantic_model_list List[Type[BaseModel]]

List of Pydantic model classes.

required
outer_object_name str

Outer object name for the GBNF grammar. If None, no outer object will be generated. Eg. "function" for function calling.

None
outer_object_content str

Content for the outer rule in the GBNF grammar. E.g., "function_parameters" or "params" for function calling.

None
model_prefix str

Prefix for the model section in the documentation.

'Output Model'
fields_prefix str

Prefix for the fields section in the documentation.

'Output Fields'
list_of_outputs bool

Whether the output is a list of items.

False
documentation_with_field_description bool

Include field descriptions in the documentation.

True
add_inner_thoughts bool

Add inner thoughts to the grammar. This is useful for adding comments or reasoning to the output.

False
allow_only_inner_thoughts bool

Allow only inner thoughts. If True, only inner thoughts will be allowed in the output.

False
inner_thoughts_field_name str

Field name for inner thoughts. Default is "thoughts_and_reasoning".

'thoughts_and_reasoning'
add_request_heartbeat bool

Add request heartbeat to the grammar. This allows the LLM to decide when to return control to the system.

False
request_heartbeat_field_name str

Field name for request heartbeat. Default is "request_heartbeat".

'request_heartbeat'
request_heartbeat_models List[str]

List of models that will have a request heartbeat field.

None

Returns:

Type Description
Tuple[str, str]

Tuple[str, str]: GBNF grammar string, documentation string.

generate_gbnf_grammar_from_pydantic_models

generate_gbnf_grammar_from_pydantic_models(
    models: list[BaseModel],
    outer_object_name: str | None = None,
    outer_object_content: str | None = None,
    list_of_outputs: bool = False,
    add_inner_thoughts: bool = True,
    allow_only_inner_thoughts: bool = True,
    inner_thought_field_name: str = "chain_of_thought",
    add_request_heartbeat: bool = True,
    request_heartbeat_field_name: str = "request_heartbeat",
    request_heartbeat_models: list[str] = None,
) -> str

Generate GBNF Grammar from Pydantic Models.

This method takes a list of Pydantic models and uses them to generate a GBNF grammar string. The generated grammar string can be used for parsing and validating data using the generated * grammar.

Parameters:

Name Type Description Default
models list[type[BaseModel]]

A list of Pydantic models to generate the grammar from.

required
outer_object_name str

Outer object name for the GBNF grammar. If None, no outer object will be generated. Eg. "function" for function calling.

None
outer_object_content str

Content for the outer rule in the GBNF grammar. Eg. "function_parameters" or "params" for function calling.

None
list_of_outputs str

Allows a list of output objects

False
add_inner_thoughts bool

Add inner thoughts to the grammar. Defaults to True.

True
allow_only_inner_thoughts bool

Allow only inner thoughts. Defaults to True.

True

Returns: str: The generated GBNF grammar string.

Examples:

models = [UserModel, PostModel] grammar = generate_gbnf_grammar_from_pydantic(models) print(grammar)

Output:

root ::= UserModel | PostModel

...

generate_gbnf_grammar_and_documentation_from_dictionaries

generate_gbnf_grammar_and_documentation_from_dictionaries(
    dictionaries: list[dict[str, Any]],
    outer_object_name: str | None = None,
    outer_object_content: str | None = None,
    model_prefix: str = "Output Model",
    fields_prefix: str = "Output Fields",
    list_of_outputs: bool = False,
    documentation_with_field_description=True,
    add_inner_thoughts: bool = False,
    allow_only_inner_thoughts: bool = False,
    inner_thoughts_field_name: str = "thoughts_and_reasoning",
    add_request_heartbeat: bool = False,
    request_heartbeat_field_name: str = "request_heartbeat",
    request_heartbeat_models: List[str] = None,
) -> Tuple[str, str]

Generate GBNF grammar and documentation from a list of dictionaries.

Parameters:

Name Type Description Default
dictionaries list[dict]

List of dictionaries representing Pydantic models.

required
outer_object_name str

Outer object name for the GBNF grammar. If None, no outer object will be generated. Eg. "function" for function calling.

None
outer_object_content str

Content for the outer rule in the GBNF grammar. Eg. "function_parameters" or "params" for function calling.

None
model_prefix str

Prefix for the model section in the documentation.

'Output Model'
fields_prefix str

Prefix for the fields section in the documentation.

'Output Fields'
list_of_outputs bool

Whether the output is a list of items.

False
documentation_with_field_description bool

Include field descriptions in the documentation.

True
add_inner_thoughts bool

Add inner thoughts to the grammar. This is useful for adding comments or reasoning to the output.

False
allow_only_inner_thoughts bool

Allow only inner thoughts. If True, only inner thoughts will be allowed in the output.

False
inner_thoughts_field_name str

Field name for inner thoughts. Default is "thoughts_and_reasoning".

'thoughts_and_reasoning'
add_request_heartbeat bool

Add request heartbeat to the grammar. This allows the LLM to decide when to return control to the system.

False
request_heartbeat_field_name str

Field name for request heartbeat. Default is "request_heartbeat".

'request_heartbeat'
request_heartbeat_models List[str]

List of models that will have a request heartbeat field.

None

Returns:

Type Description
Tuple[str, str]

Tuple[str, str]: GBNF grammar string, documentation string.

generate_and_save_gbnf_grammar_and_documentation

generate_and_save_gbnf_grammar_and_documentation(
    pydantic_model_list: List[Type[BaseModel]],
    grammar_file_path="./generated_grammar.gbnf",
    documentation_file_path="./generated_grammar_documentation.md",
    outer_object_name: str | None = None,
    outer_object_content: str | None = None,
    model_prefix: str = "Output Model",
    fields_prefix: str = "Output Fields",
    list_of_outputs: bool = False,
    documentation_with_field_description=True,
    add_inner_thoughts: bool = False,
    allow_only_inner_thoughts: bool = False,
    inner_thoughts_field_name: str = "thoughts_and_reasoning",
    add_request_heartbeat: bool = False,
    request_heartbeat_field_name: str = "request_heartbeat",
    request_heartbeat_models: List[str] = None,
)

Generate GBNF grammar and documentation, and save them to specified files.

Parameters:

Name Type Description Default
pydantic_model_list List[Type[BaseModel]]

List of Pydantic model classes.

required
grammar_file_path str

File path to save the generated GBNF grammar.

'./generated_grammar.gbnf'
documentation_file_path str

File path to save the generated documentation.

'./generated_grammar_documentation.md'
outer_object_name str

Outer object name for the GBNF grammar. If None, no outer object will be generated. Eg. "function" for function calling.

None
outer_object_content str

Content for the outer rule in the GBNF grammar. Eg. "function_parameters" or "params" for function calling.

None
model_prefix str

Prefix for the model section in the documentation.

'Output Model'
fields_prefix str

Prefix for the fields section in the documentation.

'Output Fields'
list_of_outputs bool

Whether the output is a list of items.

False
documentation_with_field_description bool

Include field descriptions in the documentation.

True
add_inner_thoughts bool

Add inner thoughts to the grammar. This is useful for adding comments or reasoning to the output.

False
allow_only_inner_thoughts bool

Allow only inner thoughts. If True, only inner thoughts will be allowed in the output.

False
inner_thoughts_field_name str

Field name for inner thoughts. Default is "thoughts_and_reasoning".

'thoughts_and_reasoning'
add_request_heartbeat bool

Add request heartbeat to the grammar. This allows the LLM to decide when to return control to the system.

False
request_heartbeat_field_name str

Field name for request heartbeat. Default is "request_heartbeat".

'request_heartbeat'
request_heartbeat_models List[str]

List of models that will have a request heartbeat field.

None

Returns: None

PydanticDataType

Bases: Enum

Defines the data types supported by the grammar_generator.

Attributes:

Name Type Description
STRING str

Represents a string data type.

BOOLEAN str

Represents a boolean data type.

INTEGER str

Represents an integer data type.

FLOAT str

Represents a float data type.

OBJECT str

Represents an object data type.

ARRAY str

Represents an array data type.

ENUM str

Represents an enum data type.

CUSTOM_CLASS str

Represents a custom class data type.

LLM Documentation

Renders Pydantic models as documentation for the model to read, so a tool's shape can be explained inside a prompt.

generate_markdown_documentation

generate_markdown_documentation(
    pydantic_models: list[type[BaseModel]],
    model_prefix="Model",
    fields_prefix="Fields",
    documentation_with_field_description=True,
    ordered_json_mode=False,
) -> str

Generate markdown documentation for a list of Pydantic models.

Parameters:

Name Type Description Default
pydantic_models list[type[BaseModel]]

list of Pydantic model classes.

required
model_prefix str

Prefix for the model section.

'Model'
fields_prefix str

Prefix for the fields section.

'Fields'
documentation_with_field_description bool

Include field descriptions in the documentation.

True

Returns:

Name Type Description
str str

Generated text documentation.

generate_text_documentation

generate_text_documentation(
    pydantic_models: list[BaseModel],
    model_prefix="Output Model",
    fields_prefix="Fields",
    documentation_with_field_description=True,
    ordered_json_mode=False,
) -> str

Generate plain-text documentation for a list of Pydantic models.

Parameters:

Name Type Description Default
pydantic_models list[type[BaseModel]]

list of Pydantic model classes.

required
model_prefix str

Prefix for the model section.

'Output Model'
fields_prefix str

Prefix for the fields section.

'Fields'
documentation_with_field_description bool

Include field descriptions in the documentation.

True
ordered_json_mode bool

Add ordering prefix for JSON schemas

False

Returns:

Name Type Description
str str

Generated text documentation.

generate_type_definitions

generate_type_definitions(types: list[type])

Pydantic Helpers

Note the module name is pydantic_utilites (the spelling in the source).

create_dynamic_model_from_function

create_dynamic_model_from_function(
    func: Callable[..., Any],
    add_inner_thoughts: bool = False,
    inner_thoughts_field_name: str = "inner_thoughts",
) -> type[BaseModel]

Creates a dynamic Pydantic model from a given function's type hints and adds the function as a 'run' method.

Parameters:

Name Type Description Default
func Callable

A function with type hints from which to create the model.

required
add_inner_thoughts bool

Add an 'inner_thoughts' field at the params level to the model. Default is False.

False
inner_thoughts_field_name str

Field name for inner thoughts. Default is "inner_thoughts".

'inner_thoughts'

Returns:

Type Description
type[BaseModel]

type[BaseModel]: A dynamic Pydantic model class with the provided function as a 'run' method.

pydantic_model_to_openai_function_definition

pydantic_model_to_openai_function_definition(
    pydantic_model: Type[BaseModel],
)

MCP Schema Conversion

Turns an MCP JSON schema into a Pydantic model, so an MCP tool becomes an ordinary FunctionTool.

convert_json_schema

convert_json_schema(schema: dict) -> type[Any]

Main entry point to convert a JSON schema to a Pydantic model.

Parameters:

Name Type Description Default
schema dict

The JSON schema dictionary

required

Returns:

Type Description
type[Any]

A Pydantic model class

convert_schema_to_pydantic_model

convert_schema_to_pydantic_model(
    dictionary: dict[str, Any],
    model_name: str = "CustomModel",
    docs: dict[str, str] = None,
    docs_function: dict[str, str] = None,
    definitions: dict[str, Any] = None,
    created_models: dict[str, Any] = None,
) -> type[Any]

Convert a JSON schema to a Pydantic model, handling complex schema features.

Parameters:

Name Type Description Default
dictionary dict[str, Any]

The JSON schema dictionary

required
model_name str

Name for the generated model

'CustomModel'
docs dict[str, str]

Documentation for fields

None
docs_function dict[str, str]

Function documentation

None
definitions dict[str, Any]

Dictionary of schema definitions

None
created_models dict[str, Any]

Dictionary of already created models to avoid duplicates

None

Returns:

Type Description
type[Any]

A Pydantic model class

MCP clients moved

ToolAgents.utilities.mcp_session is a compatibility shim. Import MCP client helpers from ToolAgents.tool_adapters.mcp_client instead.

Chat Persistence

SQLAlchemy-backed chat storage. Requires the storage extra.

ChatManager

ChatManager(db_url='sqlite:///chats.db')

session_scope

session_scope()

Provide a transactional scope around a series of operations.

create_chat

create_chat(title: Optional[str] = None) -> dict[str, Any]

Create a new chat.

add_message

add_message(
    chat_id: int, message: ChatMessage
) -> dict[str, Any]

Add a message to a chat.

get_chat

get_chat(chat_id: int) -> Optional[dict]

Get a chat by ID including all its messages.

get_chat_messages

get_chat_messages(chat_id: int) -> List[dict]

Get all messages for a chat.

delete_chat

delete_chat(chat_id: int) -> bool

Delete a chat and all its messages.

update_chat_title

update_chat_title(chat_id: int, title: str) -> bool

Update a chat's title.

Chat

Bases: Base

ChatMessageDb

Bases: Base

Logging

EasyLogger

EasyLogger(
    name: str = None,
    level: int = INFO,
    format_string: str = None,
    log_to_console: bool = True,
    log_to_file: Union[bool, str] = False,
    file_mode: str = "a",
)

A simple wrapper around Python's logging library that provides an easy interface for configuration and usage.

Initialize a new EasyLogger instance.

Parameters:

Name Type Description Default
name str

Name of the logger. If None, uses the root logger.

None
level int

The logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL).

INFO
format_string str

Custom format string for log messages. If None, uses the standard format.

None
log_to_console bool

Whether to log to the console.

True
log_to_file Union[bool, str]

If True, logs to a file with the same name as the logger. If a string, uses that as the filename.

False
file_mode str

File mode for the log file ('a' for append, 'w' for overwrite).

'a'

add_rotating_file_handler

add_rotating_file_handler(
    filename: str,
    max_bytes: int = 10 * 1024 * 1024,
    backup_count: int = 5,
)

Add a size-based rotating file handler.

Parameters:

Name Type Description Default
filename str

Path to the log file.

required
max_bytes int

Maximum size of the log file before rotating (default: 10MB).

10 * 1024 * 1024
backup_count int

Number of backup files to keep (default: 5).

5

add_timed_rotating_file_handler

add_timed_rotating_file_handler(
    filename: str,
    when: str = "midnight",
    backup_count: int = 7,
)

Add a time-based rotating file handler.

Parameters:

Name Type Description Default
filename str

Path to the log file.

required
when str

When to rotate the log file ('S', 'M', 'H', 'D', 'W0'-'W6', 'midnight'). Default is 'midnight'.

'midnight'
backup_count int

Number of backup files to keep (default: 7).

7

set_level

set_level(level: int)

Set the logging level for this logger.

debug

debug(message: Any, *args, **kwargs)

Log a debug message.

info

info(message: Any, *args, **kwargs)

Log an info message.

warning

warning(message: Any, *args, **kwargs)

Log a warning message.

error

error(message: Any, *args, **kwargs)

Log an error message.

critical

critical(message: Any, *args, **kwargs)

Log a critical message.

exception

exception(message: Any, *args, **kwargs)

Log an exception message with traceback.

silence

silence()

Temporarily silence the logger.

get_native_logger

get_native_logger()

Get the underlying Python logger instance.

configure_root_logger classmethod

configure_root_logger(
    level: int = INFO,
    format_string: str = None,
    log_to_console: bool = True,
    log_to_file: Union[bool, str] = False,
)

Configure the root logger with the given settings.

Returns an EasyLogger instance wrapped around the root logger.