Operative & Step¶
The Operative and Step classes in LionAGI provide a step-based framework for creating and handling request/response logic. These classes build upon Pydantic-based “model params” to define how data should be parsed, validated, and managed as part of a single “operation” or a multi-step workflow. They also offer convenience methods for constructing new request or response types on the fly, allowing a dynamic approach to typed exchanges.
1. Operative (operative.py
)¶
- class lionagi.operatives.operative.Operative¶
Inherits from:
SchemaModel
Purpose:
Serves as a flexible container describing how a system should handle request data (input) and produce response data (output).
References two sets of
ModelParams
: one for the request (request_params
) and one for the response (response_params
).Dynamically generates Pydantic model classes for these sets of parameters.
Key Attributes:
- request_type
/ response_type
:
The actual Pydantic model classes derived from
request_params
andresponse_params
.
response_model
: An instance of the response model, storing the final structured data (if successfully parsed).auto_retry_parse
: Whether to automatically re-try parsing if the initial parse fails.max_retries
: Maximum attempts at re-parsing or fuzzy matching.parse_kwargs
: Extra arguments for parsing logic (like fuzzy thresholds).
Key Methods:
update_response_model(text=None, data=None) -> BaseModel|dict|str|None()
Attempt to parse the provided text or dictionary into the operative’s response model. The result is stored inresponse_model
.raise_validate_pydantic(text) -> None()
Strictly validates the text by fuzzy-matching fields and raising an error on mismatch.force_validate_pydantic(text) -> None()
More lenient approach that tries to coerce or force unmatched data into the response model.create_response_type(...) -> None()
Creates a new response model type from the providedModelParams
, storing it inresponse_type
.
Usage Example:
from lionagi.operatives.operative import Operative
from lionagi.operatives.models.model_params import ModelParams
req_params = ModelParams( ... ) # define fields for request
operative = Operative(request_params=req_params)
# Suppose you have some string response from an LLM
text = '{"some_key": "some_value"}'
operative.update_response_model(text=text)
print(operative.response_model)
# => parsed Pydantic model instance (if successful)
The Operative class is especially useful when you want to define both an expected request format (input) and a response format (output) in a typed manner, ensuring the system can parse or validate them reliably.
2. Step (operative.py
)¶
- class lionagi.operatives.operative.StepModel¶
Inherits from:
BaseModel
An example Pydantic model that demonstrates how a single “operational step” might look:
title
: Title or label for the step.description
: Additional details or instructions.reason
: AReason
object capturing optional reasoning.action_requests
/action_responses
: Potential tool requests or replies associated with the step.action_required
: Boolean indicating if the step must involve a tool call.
Example:
from lionagi.operatives.operative import StepModel
step_data = {
"title": "Example Step",
"description": "A sample step requiring user input",
"action_required": True,
"action_requests": [{"function": "add", "arguments": {"x": 1, "y": 2}}],
}
step = StepModel(**step_data)
print(step.action_required) # => True
- class lionagi.operatives.operative.Step
A utility class with static methods to help you build or update
Operative
objects in a single-step context. For instance:
request_operative(...)()
Creates anOperative
geared towards request-handling (optionally adding fields like reason or actions).respond_operative(...)()
Once you have an operative with a known request format, this helps define or add the response format.
Example:
from lionagi.operatives.operative import Operative
from lionagi.operatives.operative import Step
# 1) Create an operative for requests
op = Step.request_operative(
operative_name="ExampleOperative",
reason=True,
actions=True
)
# => returns an Operative configured with reason/actions fields
# for the request model
# 2) Once you have a response to parse, you can do:
op.update_response_model(text='{"some_key": "value"}')
# => sets op.response_model if parse is successful
# 3) Or define a brand new response type:
Step.respond_operative(
operative=op,
field_models=[...],
# ... more config ...
)
Summary¶
Operative is a “two-phase” typed container describing how to handle requests and produce responses, each potentially with advanced fuzz-matching or validation.
StepModel exemplifies a single-step data structure, showing how instructions, reason, and action requests combine in a single chunk.
Step offers a convenience set of methods for creating or updating an
Operative
, bridging the gap between typed Pydantic models and real LionAGI usage, including potential tool calls (action requests).
When building multi-step flows or orchestrating larger tasks, you can use these classes to ensure consistent data structures, robust validation, and a streamlined approach to request/response handling.