Action
conatus.actions.action
¶
Action class.
ActionBlueprint
¶
Bases: type
Metaclass for the Action base classes.
This metaclass will be called whenever an Action class (not an instance)
will be defined. Note that this will be called even for subclasses at
class creation time. (At class instantiation type, it's Action.__new__
that should be called.)
identify_action_function
staticmethod
¶
Identify the action function in the class namespace.
The rules are the following: 1. If there's only one executable method defined, it's the action function. 2. Otherwise, it there's one function marked as an action function, it's the action function. 3. Otherwise, raise an error.
We use the __is_action_function attribute to identify the action
function. This attribute is added by the @Action.function decorator.
Unfortunately, there's no easy way to implement this logic in the
@Action.function decorator, since we're dealing at this stage with
classes that haven't been fully created. So we have to wait until
we are in the metaclass to do this check.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
The class name. It can't be retrieved from namespace.
TYPE:
|
namespace
|
The class namespace |
| RETURNS | DESCRIPTION |
|---|---|
Callable[Ps, ParamType]
|
The action function. |
| RAISES | DESCRIPTION |
|---|---|
ActionFunctionNotFoundError
|
If no action function was found in the class namespace. |
MultipleActionFunctionsError
|
If multiple action functions were found in the class namespace. |
ActionFunctionInferenceFoundMultipleFunctionsError
|
If multiple functions were found in the class namespace, and none of them are marked as an action function. |
Source code in conatus/actions/action.py
process_retrievability
staticmethod
¶
process_retrievability(
origin_type: ActionOriginType,
origin_module: str,
origin_qualname: str,
) -> MaybeRetrievableActionInfo
Process the retrievability of the action.
This is used to determine if the action can be retrieved in recipes.
Essentially, it asks the following question: if I were to run
from origin_module import origin_qualname, would it work? This is
necessary because if we were to run the recipe, we would need to import
the action somehow.
There are two reasons why it might not work:
- The action is defined in a <locals> namespace.
- The action is defined in a module that is not importable, such as
the Python REPL or a Jupyter notebook.
| PARAMETER | DESCRIPTION |
|---|---|
origin_type
|
The origin of the action.
TYPE:
|
origin_module
|
The module where the action was originally defined.
TYPE:
|
origin_qualname
|
The fully qualified name of the action as originally defined.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
MaybeRetrievableActionInfo
|
The retrievability info. |
Source code in conatus/actions/action.py
detect_action_function_in_bases
staticmethod
¶
Check if an action function is present in the base classes.
To be clear, the check is very crude: we just look for the presence
of the _action_function attribute in the base classes.
| PARAMETER | DESCRIPTION |
|---|---|
bases
|
Base classes of the class being created. Does not need
to be only |
| RETURNS | DESCRIPTION |
|---|---|
bool
|
True if an action function is found in the base classes, False otherwise. |
Source code in conatus/actions/action.py
__new__
¶
Create a new Action class or subclass.
As part of that process, the action function is identified and stored in the class dictionary, unless the class is a base class.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
Name of the class
TYPE:
|
bases
|
Base classes |
namespace
|
Class dictionary |
| RETURNS | DESCRIPTION |
|---|---|
type
|
New Action class |
Source code in conatus/actions/action.py
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 | |
WithConfigDescriptor
¶
WithConfigDescriptor(config_function: Callable[Ps, None])
Bases: Generic[Ps]
Descriptor to set configuration attributes on the class.
This is not meant to be used directly, but through the with_config
attribute of the Action class.
Source code in conatus/actions/action.py
config_set
staticmethod
¶
Set configuration attributes on the class or instance.
| PARAMETER | DESCRIPTION |
|---|---|
instance_or_cls
|
The class or instance
TYPE:
|
**kwargs
|
Configuration attributes to set on the class or instance
TYPE:
|
Source code in conatus/actions/action.py
__get__
¶
Get the configuration attributes of the class.
This method is called when the with_config attribute is accessed
on the class or on an instance of the class. It returns
a function that will set the configuration attributes on the class
or on the instance.
Note that the returned function does not look at the args at all.
You need to pass the configuration attributes as keyword arguments.
| PARAMETER | DESCRIPTION |
|---|---|
instance
|
The instance of the class, or None if accessed on the class.
TYPE:
|
owner
|
The class itself.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Callable[Ps, Y | type[Y]]
|
A function that will set the configuration attributes on the |
Callable[Ps, Y | type[Y]]
|
class or on the instance. |
Source code in conatus/actions/action.py
Action
¶
Base class for actions.
Warning
This class should not be instantiated directly. Instead, you should
create a subclass of Action and define an action function within it.
Private attributes¶
| ATTRIBUTE | DESCRIPTION |
|---|---|
_action_function |
The function that the action will call. This
function is created automatically if a method in a subclass
is marked with the |
retrievability_info
instance-attribute
¶
retrievability_info: (
RetrievableActionInfo | NonRetrievableActionInfo
)
Information about the retrievability of the action.
If the action is retrievable:
- this attribute is a RetrievableActionInfo
instance.
- the information enables you to retrieve the original action or function
when recipes are executed.
- you can use the get_retrievability_instructions method to get the
instructions needed to retrieve the action in a new session.
If the action is not retrievable:
- this attribute is a NonRetrievableActionInfo
instance.
- the information enables you to understand why the action is not
retrievable.
This is set automatically by the ActionBlueprint
metaclass.
always_available
instance-attribute
¶
always_available: bool
If True, the action is always available to the agent.
We determine this automatically by checking if all the parameters of the action are either JSON-serializable or optional.
Warning
Please do not set this attribute manually. If you do so, you risk breaking the agent's behavior.
discriminator_keys
instance-attribute
¶
Keys of the discriminator parameters
If not empty, the action will be available only if the agent has access to variables compatible with the discriminator parameters.
with_config
class-attribute
instance-attribute
¶
with_config = WithConfigDescriptor(_config_args)
Descriptor to set configuration attributes on the class.
How to use with_config¶
This meant to be used like a function, and it allows you to set configuration attributes on the class.
You can use it on the class itself, or on an instance of the class:
from conatus.actions.action import Action, action_function
class MyAction(Action):
desc = "Old description"
@Action.function
def my_action(self, a: int, b: int) -> int:
return a + b
# Set the configuration attribute on the class
new_action_class = MyAction.with_config(desc="New description")
assert new_action_class.desc == "New description"
# Set the configuration attribute on an instance of the class
instance = MyAction(direct_execute=False)
new_instance = instance.with_config(desc="New description")
assert new_instance.desc == "New description"
Why is with_config an attribute?
We use an attribute here because we want to be able to set configuration attributes on the class or on an instance of the class. In situations like this (where there needs to be a single call that works on both the class and the instance), a common pattern is to use a descriptor. Descriptors essentially hijack attribute access and allow you to define custom behavior when an attribute is accessed.
You can, for now, set any attribute you want on the class. We might
restrict that functionality in the future, in order to make the behavior
of with_config, and action configuration in general, more predictable.
Known issues¶
One known issue with with_config is that its return type is either
Action or TypedAction, depending on what is passed to it. This means
that type checkers will not recognize your custom subclasses. This is not
a problem if you don't define custom attributes in the class, but it you do,
and try to access these attributes on your subclass or an instance thereof,
the type checker might report attribute access issues. One work around is
to override the with_config attribute in your subclass, like so:
from conatus.actions.action import Action, WithConfigDescriptor
class MyAction(Action):
with_config: WithConfigDescriptor["MyAction"] = (
WithConfigDescriptor["MyAction"]()
)
| PARAMETER | DESCRIPTION |
|---|---|
inplace
|
If True, the configuration attributes will be set on the class or instance directly, rather than creating a new class or instance. Discouraged. Defaults to False.
TYPE:
|
**kwargs
|
Configuration attributes to set on the class. For now,
only the following attributes are supported:
-
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Action as class or instance
|
An instance of the class with the configuration attributes set, or the class itself if called on the class. |
override_type_hint_for_llm
class-attribute
instance-attribute
¶
override_type_hint_for_llm: bool = False
If True, the type hints of the function will be ignored and replaced by a more LLM-friendly version.
desc
class-attribute
instance-attribute
¶
desc: str = ''
A small, LLM-friendly description of the action.
strict_mode
instance-attribute
¶
strict_mode: bool
Whether to use strict mode when passing the action to the API.
Mostly relevant for OpenAI.
passive
class-attribute
instance-attribute
¶
passive: bool = False
Whether the action is passive.
If True, using the action during a run will not add it to the
Recipe. In other words, it's an action
that is useful for the LLM to understand the state of the world, but
useless for the runtime to execute. One characteristic of passive actions
is that they cannot return anything; the only thing they can do is
(optionally) print to the screen.
hide_if_computer_use_mode
class-attribute
instance-attribute
¶
hide_if_computer_use_mode: bool = False
Hide this action if the AI uses computer use mode.
This is meant so not as to confuse the AI by offering actions that conflict with the native capabilities of the computer use mode.
is_termination_action
class-attribute
instance-attribute
¶
is_termination_action: bool = False
Flag to indicate if the action is a termination action.
This is used to indicate that the action is a termination action, i.e. an action that generally doesn't execute anything, but rather signals the end of the conversation.
runtime_state
instance-attribute
¶
runtime_state: RuntimeState | None
Pointer to the runtime state, if available.
force_update_on
instance-attribute
¶
Names of the input variables that will be checked for changes.
function_info
property
¶
function_info: FunctionInfo
The function info of the action.
from conatus import action
@action
def double(x: int = 0) -> int:
"""Double the input.
Args:
x: The input to double.
Returns:
The double of the input.
"""
return x * 2
print(double.function_info.pretty_print())
# Function info:
# - Name: 'double'
# - Description: 'Double the input.'
# - Parameter x:
# - Description: The input to double.
# - Type hint: <class 'int'> (JSON OK)
# -- JSON-serializable subtype: <class 'int'>
# -- Type of type hint: <class 'type'>
# - Type hint shown to the LLM: 'int'
# - Required: True
# - Kind of parameter: POSITIONAL_OR_KEYWORD (1)
# - Default value: 0
# - Returns:
# - Description: The double of the input.
# - Type hint: <class 'int'>
# -- Type of type hint: <class 'type'>
# - Type hint shown to the LLM: 'int'
pydantic_models
property
¶
pydantic_models: FunctionPydanticModels
The pydantic models of the action.
The object returned is a FunctionPydanticModels
instance. From that, you can retrieve the following attributes:
input_model: The Pydantic model for the parameters of the action.output_model: The Pydantic model for the output of the action.json_schema: The Pydantic model for the JSON schema of the action.all_fields: A dictionary containing all the fields of the action, with their name as the key and a tuple of the type and theFieldInfoinstance as the value. This is mostly for internal use.
name
property
writable
¶
name: str
The name of the action function.
It is automatically set at class creation time:
- If the class is created through the @action decorator, the name will
be the name of the function that was decorated.
- If the class is created through the Action class, the name will be
the snake case version of the class name.
It can also be set manually, as long as it is not in the list of reserved action names.
openai_schema
property
¶
openai_schema: FunctionDefinition
The OpenAI schema of the action function.
json_schema
property
¶
input_model
property
¶
The Pydantic model to validate the input arguments of the action.
function
classmethod
¶
function(func: F | None = None) -> F | Callable[[F], F]
Decorator to specify an action function within an Action subclass.
This method is not meant to be called directly. This only adds a bit of metadata to the function so that the class can later find it and properly execute it.
from conatus.actions.action import Action
class MyAction(Action):
attr0 = 999
def useful_method(self, a: int) -> int:
return a + self.attr0
# Now we know this is the action function
@Action.function
def my_action(self, a: int, b: int) -> int:
return self.useful_method(a) + b
MyAction(1, 2) # This will work and return 1002
Sync functions only
This decorator is meant to be used only with sync functions. We'll support async functions in the future.
One of the effects of this decorator is that it will essentially ensure that the self argument is removed from the schema we build out of the signature and docstring of the function. This is fine 99.9% of the times, but if you have defined a static method whose first argument is somehow named self, you are going to get unexpected behavior.
| PARAMETER | DESCRIPTION |
|---|---|
func
|
The function that the action will call.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
F | Callable[[F], F]
|
The same function that was passed as an argument. |
Source code in conatus/actions/action.py
is_action
classmethod
¶
is_action(
action: Self | ActionBlueprint | FunctionType,
) -> Literal["class", "instance", "none"]
Check if the action is an instance or class of Action.
| RETURNS | DESCRIPTION |
|---|---|
Literal['class', 'instance', 'none']
|
"class" if the action is a class of |
Source code in conatus/actions/action.py
__deepcopy__
¶
Deepcopy the action.
This method is called when a deep copy of the action is made.
| PARAMETER | DESCRIPTION |
|---|---|
memo
|
The memo dictionary. |
| RETURNS | DESCRIPTION |
|---|---|
Self
|
The deep copy of the action. |
Source code in conatus/actions/action.py
__new__
¶
Create a new Action instance.
This method is called when a new instance of an Action class is
created. It will call the action function with the arguments passed and
return the result, or the instance itself if direct_execute is set to
False.
| PARAMETER | DESCRIPTION |
|---|---|
*args
|
Positional arguments passed to the action function.
TYPE:
|
direct_execute
|
If True, the action function will be called with the arguments passed to the constructor. If False, the instance will be returned.
TYPE:
|
**kwargs
|
Keyword arguments passed to the action function.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ParamType | Self
|
The result of the action function if |
ParamType | Self
|
the instance itself otherwise. |
Source code in conatus/actions/action.py
__call__
¶
Call the action function.
This is a convenience method that allows you to call the action
function directly on the instance of the Action class.
This method does not check whether the underlying action function is async or not; you have to deal with that yourself.
from conatus.actions.action import action
@action
async def async_action(x: int) -> int:
return x
x = 10
assert await async_action(x) == x
@action
def sync_action_2(x: int) -> int:
return x
assert sync_action_2(x) == x
| PARAMETER | DESCRIPTION |
|---|---|
*args
|
Positional arguments passed to the action function.
TYPE:
|
**kwargs
|
Keyword arguments passed to the action function.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ParamType
|
The result of the action function. |
Source code in conatus/actions/action.py
__setattr__
¶
Set an attribute on the instance.
We use this function to intercept attribute changes.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
The name of the attribute.
TYPE:
|
value
|
The value of the attribute.
TYPE:
|
Source code in conatus/actions/action.py
execute
¶
Explicit execution of the action function.
This is useful if you've created an instance of an Action class with
direct_execute=False and you want to execute the action function
afterwards. This is also a way to make type checkers happy.
from conatus.actions.action import Action
class MyAction(Action):
@Action.function
def my_action(self, a: int, b: int) -> int:
return a + b
assert MyAction(1, 2) == 3 # This will work like a function call...
# ... unless you want to separate it in two steps
instance = MyAction(direct_execute=False)
assert type(instance) == MyAction
assert instance.execute(1, 2) == 3
| PARAMETER | DESCRIPTION |
|---|---|
*args
|
Positional arguments passed to the action function.
TYPE:
|
**kwargs
|
Keyword arguments passed to the action function.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
ParamType
|
The result of the action function. |
Source code in conatus/actions/action.py
get_openai_schema
¶
get_openai_schema(
*, strict_mode: bool
) -> FunctionDefinition
The OpenAI schema of the action function.
This method is meant to be used if you want to explicitly pass the
strict_mode argument to the get_openai_schema method. Otherwise,
you should use the openai_schema property. This is why strict_mode
is a required argument.
| PARAMETER | DESCRIPTION |
|---|---|
strict_mode
|
If True, the schema will be generated in strict mode. If False, the schema will be generated in non-strict mode.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
FunctionDefinition
|
The OpenAI schema of the action function. |
Source code in conatus/actions/action.py
pretty_function_info
¶
get_maybe_recipe_retrievability_warnings
¶
get_maybe_recipe_retrievability_warnings(
i: int, *, with_first_message: bool = True
) -> str | None
Generate a warning message if the action is not retrievable.
Useful when are creating an Agent
and want to display the warnings then.
| PARAMETER | DESCRIPTION |
|---|---|
i
|
The index of the action in the list of actions
TYPE:
|
with_first_message
|
If True, the first message will be included. Defaults to True.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str | None
|
The warning message if the action is not retrievable, or None |
str | None
|
otherwise. |
Source code in conatus/actions/action.py
get_maybe_recipe_retrievability_instructions
¶
get_maybe_recipe_retrievability_instructions() -> (
RetrievabilityInstructions | None
)
Get the retrievability instructions for the action.
If the action is not retrievable, returns None.
In general, there should be no surprises with this method. If you
have established that the action is retrievable, (by asserting that
action.retrievability_info
is an instance of
RetrievableActionInfo
),
then you should be sure that this method will the instructions.
Nevertheless, if the JSON serialization of the changes fails,
we will raise a TypeError.
| RETURNS | DESCRIPTION |
|---|---|
RetrievabilityInstructions | None
|
The retrievability instructions for the action, or None if the |
RetrievabilityInstructions | None
|
action is not retrievable. |
| RAISES | DESCRIPTION |
|---|---|
TypeError
|
If the changes are not JSON serializable. |
Source code in conatus/actions/action.py
get_docstring
¶
Get the docstring of the action.
This docstring is meant to be used in the AI interfaces.
We convert it to Numpy style because we don't have to deal with the indentation of the parameters.
| PARAMETER | DESCRIPTION |
|---|---|
include_name
|
Whether to include the name of the action in the docstring. Defaults to True.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str
|
The docstring.
TYPE:
|
Source code in conatus/actions/action.py
1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 | |
add_runtime_state
¶
add_runtime_state(runtime_state: RuntimeState) -> None
Add a pointer to the runtime state to the action.
This is useful if you want to use the runtime state in the action.
| PARAMETER | DESCRIPTION |
|---|---|
runtime_state
|
The runtime state to add to the action.
TYPE:
|
Source code in conatus/actions/action.py
force_variable_update
¶
force_variable_update(variable: ParamType) -> None
Force a variable update.
An Action, especially passive
ones, can force a variable update.
This is useful, for instance, if you want to ensure that a browser screenshot is saved at a given step.
Note that we compare the variable object by checking its id.
If the variable object is present multiple times in the runtime state,
it will be updated in all of them.
| PARAMETER | DESCRIPTION |
|---|---|
variable
|
The variable to update.
TYPE:
|
Source code in conatus/actions/action.py
check_params
¶
Check the parameters of the action.
This method is used to check the parameters of the action.
| PARAMETER | DESCRIPTION |
|---|---|
*args
|
Positional arguments passed to the action function.
TYPE:
|
**kwargs
|
Keyword arguments passed to the action function.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, ParamType]
|
A dictionary with the parameters as keys and their values as values. |
Source code in conatus/actions/action.py
TypedAction
¶
Base class for typed actions.
Warning
This class should not be instantiated directly. Instead, you should
create a subclass of TypedAction and define an action function within
it.
| ATTRIBUTE | DESCRIPTION |
|---|---|
_action_function |
The function that the action will call. See more in
the
TYPE:
|
retrievability_info
instance-attribute
¶
retrievability_info: (
RetrievableActionInfo | NonRetrievableActionInfo
)
Information about the retrievability of the action.
If the action is retrievable:
- this attribute is a RetrievableActionInfo
instance.
- the information enables you to retrieve the original action or function
when recipes are executed.
- you can use the get_retrievability_instructions method to get the
instructions needed to retrieve the action in a new session.
If the action is not retrievable:
- this attribute is a NonRetrievableActionInfo
instance.
- the information enables you to understand why the action is not
retrievable.
This is set automatically by the ActionBlueprint
metaclass.
always_available
instance-attribute
¶
always_available: bool
If True, the action is always available to the agent.
We determine this automatically by checking if all the parameters of the action are either JSON-serializable or optional.
Warning
Please do not set this attribute manually. If you do so, you risk breaking the agent's behavior.
discriminator_keys
instance-attribute
¶
Keys of the discriminator parameters
If not empty, the action will be available only if the agent has access to variables compatible with the discriminator parameters.
override_type_hint_for_llm
class-attribute
instance-attribute
¶
override_type_hint_for_llm: bool = False
If True, the type hints of the function will be ignored and replaced by a more LLM-friendly version.
desc
class-attribute
instance-attribute
¶
desc: str = ''
A small, LLM-friendly description of the action.
passive
class-attribute
instance-attribute
¶
passive: bool = False
Whether the action is passive.
If True, using the action during a run will not add it to the
Recipe. In other words, it's an action
that is useful for the LLM to understand the state of the world, but
useless for the runtime to execute. One characteristic of passive actions
is that they cannot return anything; the only thing they can do is
(optionally) print to the screen.
hide_if_computer_use_mode
class-attribute
instance-attribute
¶
hide_if_computer_use_mode: bool = False
Hide this action if the AI uses computer use mode.
This is meant so not as to confuse the AI by offering actions that conflict with the native capabilities of the computer use mode.
is_termination_action
class-attribute
instance-attribute
¶
is_termination_action: bool = False
Flag to indicate if the action is a termination action.
This is used to indicate that the action is a termination action, i.e. an action that generally doesn't execute anything, but rather signals the end of the conversation.
runtime_state
instance-attribute
¶
runtime_state: RuntimeState | None
Pointer to the runtime state, if available.
force_update_on
instance-attribute
¶
Names of the input variables that will be checked for changes.
function_info
property
¶
function_info: FunctionInfo
The function info of the action.
from conatus import action
@action
def double(x: int = 0) -> int:
"""Double the input.
Args:
x: The input to double.
Returns:
The double of the input.
"""
return x * 2
print(double.function_info.pretty_print())
# Function info:
# - Name: 'double'
# - Description: 'Double the input.'
# - Parameter x:
# - Description: The input to double.
# - Type hint: <class 'int'> (JSON OK)
# -- JSON-serializable subtype: <class 'int'>
# -- Type of type hint: <class 'type'>
# - Type hint shown to the LLM: 'int'
# - Required: True
# - Kind of parameter: POSITIONAL_OR_KEYWORD (1)
# - Default value: 0
# - Returns:
# - Description: The double of the input.
# - Type hint: <class 'int'>
# -- Type of type hint: <class 'type'>
# - Type hint shown to the LLM: 'int'
pydantic_models
property
¶
pydantic_models: FunctionPydanticModels
The pydantic models of the action.
The object returned is a FunctionPydanticModels
instance. From that, you can retrieve the following attributes:
input_model: The Pydantic model for the parameters of the action.output_model: The Pydantic model for the output of the action.json_schema: The Pydantic model for the JSON schema of the action.all_fields: A dictionary containing all the fields of the action, with their name as the key and a tuple of the type and theFieldInfoinstance as the value. This is mostly for internal use.
name
property
writable
¶
name: str
The name of the action function.
It is automatically set at class creation time:
- If the class is created through the @action decorator, the name will
be the name of the function that was decorated.
- If the class is created through the Action class, the name will be
the snake case version of the class name.
It can also be set manually, as long as it is not in the list of reserved action names.
openai_schema
property
¶
openai_schema: FunctionDefinition
The OpenAI schema of the action function.
json_schema
property
¶
input_model
property
¶
The Pydantic model to validate the input arguments of the action.
__new__
¶
__new__(
direct_execute: Literal[False],
*args: None,
**kwargs: None
) -> Self
Create a new TypedAction instance.
This method is called when a new instance of a TypedAction class is
created. It will call the action function with the arguments passed and
return the result, or the instance itself if direct_execute is set to
False.
| PARAMETER | DESCRIPTION |
|---|---|
*args
|
Positional arguments passed to the action function.
TYPE:
|
**kwargs: Keyword arguments passed to the action function.
| PARAMETER | DESCRIPTION |
|---|---|
direct_execute |
If
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
R | Self
|
The result of the action function if |
R | Self
|
the instance itself otherwise. |
Source code in conatus/actions/action.py
__call__
¶
Call the action function.
This is a convenience method that allows you to call the action
function directly on the instance of the TypedAction class.
| PARAMETER | DESCRIPTION |
|---|---|
*args
|
Positional arguments passed to the action function.
TYPE:
|
**kwargs
|
Keyword arguments passed to the action function.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
R
|
The result of the action function. |
Source code in conatus/actions/action.py
execute
¶
Explicit execution of the action function.
This is useful if you've created an instance of an Action class with
direct_execute=False and you want to execute the action function
afterwards. This is also a way to make type checkers happy.
from conatus.actions.action import TypedAction, action_function
from typing import Concatenate
class MyTypedAction(TypedAction[Concatenate[int, int], int]):
@Action.function
def my_action(self, a: int, b: int) -> int:
return a + b
assert MyTypedAction(1, 2) == 3 # This will work like a function...
# ... unless you want to separate it in two steps
instance = MyTypedAction(direct_execute=False)
assert type(instance) == MyTypedAction
assert instance.execute(1, 2) == 3
| PARAMETER | DESCRIPTION |
|---|---|
*args
|
Positional arguments passed to the action function.
TYPE:
|
**kwargs
|
Keyword arguments passed to the action function.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
R
|
The result of the action function. |
Source code in conatus/actions/action.py
function
classmethod
¶
function(func: F | None = None) -> F | Callable[[F], F]
Decorator to specify an action function within an Action subclass.
This method is not meant to be called directly. This only adds a bit of metadata to the function so that the class can later find it and properly execute it.
from conatus.actions.action import Action
class MyAction(Action):
attr0 = 999
def useful_method(self, a: int) -> int:
return a + self.attr0
# Now we know this is the action function
@Action.function
def my_action(self, a: int, b: int) -> int:
return self.useful_method(a) + b
MyAction(1, 2) # This will work and return 1002
Sync functions only
This decorator is meant to be used only with sync functions. We'll support async functions in the future.
One of the effects of this decorator is that it will essentially ensure that the self argument is removed from the schema we build out of the signature and docstring of the function. This is fine 99.9% of the times, but if you have defined a static method whose first argument is somehow named self, you are going to get unexpected behavior.
| PARAMETER | DESCRIPTION |
|---|---|
func
|
The function that the action will call.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
F | Callable[[F], F]
|
The same function that was passed as an argument. |
Source code in conatus/actions/action.py
is_action
classmethod
¶
is_action(
action: Self | ActionBlueprint | FunctionType,
) -> Literal["class", "instance", "none"]
Check if the action is an instance or class of Action.
| RETURNS | DESCRIPTION |
|---|---|
Literal['class', 'instance', 'none']
|
"class" if the action is a class of |
Source code in conatus/actions/action.py
__deepcopy__
¶
Deepcopy the action.
This method is called when a deep copy of the action is made.
| PARAMETER | DESCRIPTION |
|---|---|
memo
|
The memo dictionary. |
| RETURNS | DESCRIPTION |
|---|---|
Self
|
The deep copy of the action. |
Source code in conatus/actions/action.py
__setattr__
¶
Set an attribute on the instance.
We use this function to intercept attribute changes.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
The name of the attribute.
TYPE:
|
value
|
The value of the attribute.
TYPE:
|
Source code in conatus/actions/action.py
get_openai_schema
¶
get_openai_schema(
*, strict_mode: bool
) -> FunctionDefinition
The OpenAI schema of the action function.
This method is meant to be used if you want to explicitly pass the
strict_mode argument to the get_openai_schema method. Otherwise,
you should use the openai_schema property. This is why strict_mode
is a required argument.
| PARAMETER | DESCRIPTION |
|---|---|
strict_mode
|
If True, the schema will be generated in strict mode. If False, the schema will be generated in non-strict mode.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
FunctionDefinition
|
The OpenAI schema of the action function. |
Source code in conatus/actions/action.py
pretty_function_info
¶
get_maybe_recipe_retrievability_warnings
¶
get_maybe_recipe_retrievability_warnings(
i: int, *, with_first_message: bool = True
) -> str | None
Generate a warning message if the action is not retrievable.
Useful when are creating an Agent
and want to display the warnings then.
| PARAMETER | DESCRIPTION |
|---|---|
i
|
The index of the action in the list of actions
TYPE:
|
with_first_message
|
If True, the first message will be included. Defaults to True.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str | None
|
The warning message if the action is not retrievable, or None |
str | None
|
otherwise. |
Source code in conatus/actions/action.py
get_maybe_recipe_retrievability_instructions
¶
get_maybe_recipe_retrievability_instructions() -> (
RetrievabilityInstructions | None
)
Get the retrievability instructions for the action.
If the action is not retrievable, returns None.
In general, there should be no surprises with this method. If you
have established that the action is retrievable, (by asserting that
action.retrievability_info
is an instance of
RetrievableActionInfo
),
then you should be sure that this method will the instructions.
Nevertheless, if the JSON serialization of the changes fails,
we will raise a TypeError.
| RETURNS | DESCRIPTION |
|---|---|
RetrievabilityInstructions | None
|
The retrievability instructions for the action, or None if the |
RetrievabilityInstructions | None
|
action is not retrievable. |
| RAISES | DESCRIPTION |
|---|---|
TypeError
|
If the changes are not JSON serializable. |
Source code in conatus/actions/action.py
get_docstring
¶
Get the docstring of the action.
This docstring is meant to be used in the AI interfaces.
We convert it to Numpy style because we don't have to deal with the indentation of the parameters.
| PARAMETER | DESCRIPTION |
|---|---|
include_name
|
Whether to include the name of the action in the docstring. Defaults to True.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str
|
The docstring.
TYPE:
|
Source code in conatus/actions/action.py
1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 | |
add_runtime_state
¶
add_runtime_state(runtime_state: RuntimeState) -> None
Add a pointer to the runtime state to the action.
This is useful if you want to use the runtime state in the action.
| PARAMETER | DESCRIPTION |
|---|---|
runtime_state
|
The runtime state to add to the action.
TYPE:
|
Source code in conatus/actions/action.py
force_variable_update
¶
force_variable_update(variable: ParamType) -> None
Force a variable update.
An Action, especially passive
ones, can force a variable update.
This is useful, for instance, if you want to ensure that a browser screenshot is saved at a given step.
Note that we compare the variable object by checking its id.
If the variable object is present multiple times in the runtime state,
it will be updated in all of them.
| PARAMETER | DESCRIPTION |
|---|---|
variable
|
The variable to update.
TYPE:
|
Source code in conatus/actions/action.py
check_params
¶
Check the parameters of the action.
This method is used to check the parameters of the action.
| PARAMETER | DESCRIPTION |
|---|---|
*args
|
Positional arguments passed to the action function.
TYPE:
|
**kwargs
|
Keyword arguments passed to the action function.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, ParamType]
|
A dictionary with the parameters as keys and their values as values. |
Source code in conatus/actions/action.py
UntypedAction
¶
Bases: TypedAction[P, ParamType]
Untyped action.
retrievability_info
instance-attribute
¶
retrievability_info: (
RetrievableActionInfo | NonRetrievableActionInfo
)
Information about the retrievability of the action.
If the action is retrievable:
- this attribute is a RetrievableActionInfo
instance.
- the information enables you to retrieve the original action or function
when recipes are executed.
- you can use the get_retrievability_instructions method to get the
instructions needed to retrieve the action in a new session.
If the action is not retrievable:
- this attribute is a NonRetrievableActionInfo
instance.
- the information enables you to understand why the action is not
retrievable.
This is set automatically by the ActionBlueprint
metaclass.
always_available
instance-attribute
¶
always_available: bool
If True, the action is always available to the agent.
We determine this automatically by checking if all the parameters of the action are either JSON-serializable or optional.
Warning
Please do not set this attribute manually. If you do so, you risk breaking the agent's behavior.
discriminator_keys
instance-attribute
¶
Keys of the discriminator parameters
If not empty, the action will be available only if the agent has access to variables compatible with the discriminator parameters.
override_type_hint_for_llm
class-attribute
instance-attribute
¶
override_type_hint_for_llm: bool = False
If True, the type hints of the function will be ignored and replaced by a more LLM-friendly version.
desc
class-attribute
instance-attribute
¶
desc: str = ''
A small, LLM-friendly description of the action.
passive
class-attribute
instance-attribute
¶
passive: bool = False
Whether the action is passive.
If True, using the action during a run will not add it to the
Recipe. In other words, it's an action
that is useful for the LLM to understand the state of the world, but
useless for the runtime to execute. One characteristic of passive actions
is that they cannot return anything; the only thing they can do is
(optionally) print to the screen.
hide_if_computer_use_mode
class-attribute
instance-attribute
¶
hide_if_computer_use_mode: bool = False
Hide this action if the AI uses computer use mode.
This is meant so not as to confuse the AI by offering actions that conflict with the native capabilities of the computer use mode.
is_termination_action
class-attribute
instance-attribute
¶
is_termination_action: bool = False
Flag to indicate if the action is a termination action.
This is used to indicate that the action is a termination action, i.e. an action that generally doesn't execute anything, but rather signals the end of the conversation.
runtime_state
instance-attribute
¶
runtime_state: RuntimeState | None
Pointer to the runtime state, if available.
force_update_on
instance-attribute
¶
Names of the input variables that will be checked for changes.
function_info
property
¶
function_info: FunctionInfo
The function info of the action.
from conatus import action
@action
def double(x: int = 0) -> int:
"""Double the input.
Args:
x: The input to double.
Returns:
The double of the input.
"""
return x * 2
print(double.function_info.pretty_print())
# Function info:
# - Name: 'double'
# - Description: 'Double the input.'
# - Parameter x:
# - Description: The input to double.
# - Type hint: <class 'int'> (JSON OK)
# -- JSON-serializable subtype: <class 'int'>
# -- Type of type hint: <class 'type'>
# - Type hint shown to the LLM: 'int'
# - Required: True
# - Kind of parameter: POSITIONAL_OR_KEYWORD (1)
# - Default value: 0
# - Returns:
# - Description: The double of the input.
# - Type hint: <class 'int'>
# -- Type of type hint: <class 'type'>
# - Type hint shown to the LLM: 'int'
pydantic_models
property
¶
pydantic_models: FunctionPydanticModels
The pydantic models of the action.
The object returned is a FunctionPydanticModels
instance. From that, you can retrieve the following attributes:
input_model: The Pydantic model for the parameters of the action.output_model: The Pydantic model for the output of the action.json_schema: The Pydantic model for the JSON schema of the action.all_fields: A dictionary containing all the fields of the action, with their name as the key and a tuple of the type and theFieldInfoinstance as the value. This is mostly for internal use.
name
property
writable
¶
name: str
The name of the action function.
It is automatically set at class creation time:
- If the class is created through the @action decorator, the name will
be the name of the function that was decorated.
- If the class is created through the Action class, the name will be
the snake case version of the class name.
It can also be set manually, as long as it is not in the list of reserved action names.
openai_schema
property
¶
openai_schema: FunctionDefinition
The OpenAI schema of the action function.
json_schema
property
¶
input_model
property
¶
The Pydantic model to validate the input arguments of the action.
function
classmethod
¶
function(func: F | None = None) -> F | Callable[[F], F]
Decorator to specify an action function within an Action subclass.
This method is not meant to be called directly. This only adds a bit of metadata to the function so that the class can later find it and properly execute it.
from conatus.actions.action import Action
class MyAction(Action):
attr0 = 999
def useful_method(self, a: int) -> int:
return a + self.attr0
# Now we know this is the action function
@Action.function
def my_action(self, a: int, b: int) -> int:
return self.useful_method(a) + b
MyAction(1, 2) # This will work and return 1002
Sync functions only
This decorator is meant to be used only with sync functions. We'll support async functions in the future.
One of the effects of this decorator is that it will essentially ensure that the self argument is removed from the schema we build out of the signature and docstring of the function. This is fine 99.9% of the times, but if you have defined a static method whose first argument is somehow named self, you are going to get unexpected behavior.
| PARAMETER | DESCRIPTION |
|---|---|
func
|
The function that the action will call.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
F | Callable[[F], F]
|
The same function that was passed as an argument. |
Source code in conatus/actions/action.py
is_action
classmethod
¶
is_action(
action: Self | ActionBlueprint | FunctionType,
) -> Literal["class", "instance", "none"]
Check if the action is an instance or class of Action.
| RETURNS | DESCRIPTION |
|---|---|
Literal['class', 'instance', 'none']
|
"class" if the action is a class of |
Source code in conatus/actions/action.py
__deepcopy__
¶
Deepcopy the action.
This method is called when a deep copy of the action is made.
| PARAMETER | DESCRIPTION |
|---|---|
memo
|
The memo dictionary. |
| RETURNS | DESCRIPTION |
|---|---|
Self
|
The deep copy of the action. |
Source code in conatus/actions/action.py
__new__
¶
__new__(
direct_execute: Literal[False],
*args: None,
**kwargs: None
) -> Self
Create a new TypedAction instance.
This method is called when a new instance of a TypedAction class is
created. It will call the action function with the arguments passed and
return the result, or the instance itself if direct_execute is set to
False.
| PARAMETER | DESCRIPTION |
|---|---|
*args
|
Positional arguments passed to the action function.
TYPE:
|
**kwargs: Keyword arguments passed to the action function.
| PARAMETER | DESCRIPTION |
|---|---|
direct_execute |
If
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
R | Self
|
The result of the action function if |
R | Self
|
the instance itself otherwise. |
Source code in conatus/actions/action.py
__call__
¶
Call the action function.
This is a convenience method that allows you to call the action
function directly on the instance of the TypedAction class.
| PARAMETER | DESCRIPTION |
|---|---|
*args
|
Positional arguments passed to the action function.
TYPE:
|
**kwargs
|
Keyword arguments passed to the action function.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
R
|
The result of the action function. |
Source code in conatus/actions/action.py
__setattr__
¶
Set an attribute on the instance.
We use this function to intercept attribute changes.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
The name of the attribute.
TYPE:
|
value
|
The value of the attribute.
TYPE:
|
Source code in conatus/actions/action.py
execute
¶
Explicit execution of the action function.
This is useful if you've created an instance of an Action class with
direct_execute=False and you want to execute the action function
afterwards. This is also a way to make type checkers happy.
from conatus.actions.action import TypedAction, action_function
from typing import Concatenate
class MyTypedAction(TypedAction[Concatenate[int, int], int]):
@Action.function
def my_action(self, a: int, b: int) -> int:
return a + b
assert MyTypedAction(1, 2) == 3 # This will work like a function...
# ... unless you want to separate it in two steps
instance = MyTypedAction(direct_execute=False)
assert type(instance) == MyTypedAction
assert instance.execute(1, 2) == 3
| PARAMETER | DESCRIPTION |
|---|---|
*args
|
Positional arguments passed to the action function.
TYPE:
|
**kwargs
|
Keyword arguments passed to the action function.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
R
|
The result of the action function. |
Source code in conatus/actions/action.py
get_openai_schema
¶
get_openai_schema(
*, strict_mode: bool
) -> FunctionDefinition
The OpenAI schema of the action function.
This method is meant to be used if you want to explicitly pass the
strict_mode argument to the get_openai_schema method. Otherwise,
you should use the openai_schema property. This is why strict_mode
is a required argument.
| PARAMETER | DESCRIPTION |
|---|---|
strict_mode
|
If True, the schema will be generated in strict mode. If False, the schema will be generated in non-strict mode.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
FunctionDefinition
|
The OpenAI schema of the action function. |
Source code in conatus/actions/action.py
pretty_function_info
¶
get_maybe_recipe_retrievability_warnings
¶
get_maybe_recipe_retrievability_warnings(
i: int, *, with_first_message: bool = True
) -> str | None
Generate a warning message if the action is not retrievable.
Useful when are creating an Agent
and want to display the warnings then.
| PARAMETER | DESCRIPTION |
|---|---|
i
|
The index of the action in the list of actions
TYPE:
|
with_first_message
|
If True, the first message will be included. Defaults to True.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str | None
|
The warning message if the action is not retrievable, or None |
str | None
|
otherwise. |
Source code in conatus/actions/action.py
get_maybe_recipe_retrievability_instructions
¶
get_maybe_recipe_retrievability_instructions() -> (
RetrievabilityInstructions | None
)
Get the retrievability instructions for the action.
If the action is not retrievable, returns None.
In general, there should be no surprises with this method. If you
have established that the action is retrievable, (by asserting that
action.retrievability_info
is an instance of
RetrievableActionInfo
),
then you should be sure that this method will the instructions.
Nevertheless, if the JSON serialization of the changes fails,
we will raise a TypeError.
| RETURNS | DESCRIPTION |
|---|---|
RetrievabilityInstructions | None
|
The retrievability instructions for the action, or None if the |
RetrievabilityInstructions | None
|
action is not retrievable. |
| RAISES | DESCRIPTION |
|---|---|
TypeError
|
If the changes are not JSON serializable. |
Source code in conatus/actions/action.py
get_docstring
¶
Get the docstring of the action.
This docstring is meant to be used in the AI interfaces.
We convert it to Numpy style because we don't have to deal with the indentation of the parameters.
| PARAMETER | DESCRIPTION |
|---|---|
include_name
|
Whether to include the name of the action in the docstring. Defaults to True.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str
|
The docstring.
TYPE:
|
Source code in conatus/actions/action.py
1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 | |
add_runtime_state
¶
add_runtime_state(runtime_state: RuntimeState) -> None
Add a pointer to the runtime state to the action.
This is useful if you want to use the runtime state in the action.
| PARAMETER | DESCRIPTION |
|---|---|
runtime_state
|
The runtime state to add to the action.
TYPE:
|
Source code in conatus/actions/action.py
force_variable_update
¶
force_variable_update(variable: ParamType) -> None
Force a variable update.
An Action, especially passive
ones, can force a variable update.
This is useful, for instance, if you want to ensure that a browser screenshot is saved at a given step.
Note that we compare the variable object by checking its id.
If the variable object is present multiple times in the runtime state,
it will be updated in all of them.
| PARAMETER | DESCRIPTION |
|---|---|
variable
|
The variable to update.
TYPE:
|
Source code in conatus/actions/action.py
check_params
¶
Check the parameters of the action.
This method is used to check the parameters of the action.
| PARAMETER | DESCRIPTION |
|---|---|
*args
|
Positional arguments passed to the action function.
TYPE:
|
**kwargs
|
Keyword arguments passed to the action function.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, ParamType]
|
A dictionary with the parameters as keys and their values as values. |
Source code in conatus/actions/action.py
is_action_function
¶
Internal function to check if a function is an action function.
To be used in conjunction with @Action.function and
mark_action_function
from conatus.actions.action import is_action_function, Action
class MyAction(Action):
@Action.function
def my_action(self, a: int, b: int) -> int:
return a + b
assert is_action_function(MyAction.my_action) # True
| PARAMETER | DESCRIPTION |
|---|---|
func
|
The function to check. |
| RETURNS | DESCRIPTION |
|---|---|
bool
|
True if the function is an action function, False otherwise. |
Source code in conatus/actions/action.py
mark_action_function
¶
Internal function to mark a method as an action function.
Can be used in conjunction with is_action_function and
@Action.function
from conatus.actions.action import mark_action_function, is_action_function
def a_function(a: int, b: int) -> int:
return a + b
assert not is_action_function(a_function) # False
assert is_action_function(mark_action_function(a_function)) # True
| RETURNS | DESCRIPTION |
|---|---|
F
|
The same function that was passed as an argument. |
Source code in conatus/actions/action.py
to_snake_case
¶
determine_always_available
¶
determine_always_available(
function_info: FunctionInfo,
) -> tuple[bool, list[str]]
Determine what the action needs to be available.
| PARAMETER | DESCRIPTION |
|---|---|
function_info
|
The function info.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
bool
|
True if the action is always available, False otherwise. |
list[str]
|
The discriminator keys if the action is sometimes available, an empty list otherwise. |
Source code in conatus/actions/action.py
conatus.actions.decorators
¶
Decorators for the Action class.
action
¶
action() -> (
Callable[[Callable[P, R]], TypedAction[P, R]]
)
action(func: Callable[P, R]) -> TypedAction[P, R]
action(
func: Callable[P, R],
/,
*,
as_passthrough: bool = False,
desc: str | None = None,
override_type_hint_for_llm: bool = False,
suppress_strict_mode_warning: bool = False,
passive: bool = False,
hide_if_computer_use_mode: bool = False,
force_update_on: str | list[str] | None = None,
) -> TypedAction[P, R]
action(
*,
as_passthrough: Literal[False] = False,
override_type_hint_for_llm: bool = False,
desc: str | None = None,
suppress_strict_mode_warning: bool = False,
passive: bool = False,
hide_if_computer_use_mode: bool = False,
force_update_on: str | list[str] | None = None
) -> Callable[[Callable[P, R]], TypedAction[P, R]]
action(
*,
as_passthrough: Literal[True],
desc: str | None = None,
override_type_hint_for_llm: bool = False,
suppress_strict_mode_warning: bool = False,
passive: bool = False,
hide_if_computer_use_mode: bool = False,
force_update_on: str | list[str] | None = None
) -> Callable[[Callable[P, R]], Callable[P, R]]
action(
func: Callable[P, R] | None = None,
/,
*,
as_passthrough: bool = False,
desc: str | None = None,
override_type_hint_for_llm: bool = False,
suppress_strict_mode_warning: bool = False,
passive: bool = False,
hide_if_computer_use_mode: bool = False,
force_update_on: str | list[str] | None = None,
) -> (
TypedAction[P, R]
| Callable[[Callable[P, R]], TypedAction[P, R]]
| Callable[[Callable[P, R]], Callable[P, R]]
)
Decorator to create an Action subclass.
This decorator takes a function and returns an Action in a somewhat
transparent way. You can use it as a decorator or a function, with or
without arguments.
from conatus.actions.decorators import action
# You can use `action` as a decorator
@action
def multiply_by_two(x: int) -> int:
return x * 2
# It looks like a normal function, but you get things like type-checking,
# meaning `multiply_by_two("five")` will not work
assert multiply_by_two(5) == 10
# You can also use `action` as a function
def multiply_by_ten(x: int) -> int:
return x * 10
MultiplyByTen = action(multiply_by_ten)
assert MultiplyByTen(5) == 50
Passthrough mode¶
Passthrough mode is useful when you want to use the action decorator
to transform an instance method into an Action subclass. Doing so is
actually tricker than it appears. Consider this:
from dataclasses import dataclass
@dataclass
class MyClass:
attribute: int = 10
def my_fn(self, x: int) -> int:
return x + self.attribute
# You can call the function in two ways:
assert MyClass.my_fn(MyClass(), 5) == 15
assert MyClass(attribute=20).my_fn(5) == 25
The problem is that my_fn has two different signatures based on the
context in which it is called. Unfortunately, if we convert my_fn to
an Action, the type-checker will lose the ability to understand that
nuance. There's really no way around it.
Which means that, if you want to use the @action decorator on an
instance method, you have two choices:
-
You can use
@actionas is, and the method will be transformed to aTypedAction. But this means that the type-checker will be demand that you pass an instance of your class as the first argument of your method, regardless of whether that method is attached to a live instance. Concretely:from conatus.actions.action import TypedAction from conatus.actions.decorators import action @dataclass class MyClass: attribute: int = 10 @action def my_fn(self, x: int) -> int: return x + self.attribute assert type(MyClass.my_fn) is TypedAction # Works fine with your type-checker assert MyClass.my_fn(MyClass(), 5) == 15 # This works, but your type checker will want you to write instead: # MyClass().my_fn(attribute=20, 5) assert MyClass(attribute=20).my_fn(5) == 25 -
You can use
@action(as_passthrough=True). This will tell the type checker that the function is returned without any changes, even though it is actually aTypedAction. This will solve the problem above. But it comes with one trade-off: you will not be able to access properties traditionally associated with anAction:from conatus.actions.action import TypedAction from conatus.actions.decorators import action @dataclass class MyClass: attribute: int = 10 @action(as_passthrough=True) def my_fn(self, x: int) -> int: return x + self.attribute assert type(MyClass.my_fn) is not TypedAction # Works fine now with your type-checker assert MyClass(attribute=20).my_fn(5) == 25 # This will not work anymore, since MyClass is a callable assert getattr("_function_info", MyClass.my_fn, None) is None # But you can retrieve the underlying action as such: assert type(getattr("_action", MyClass.my_fn, None)) is TypedAction
Because the passthrough mode approach forces us to return something that is
not an Action, it is disabled by default, even when we detect that the
@action decorator is being used on an instance method.
| PARAMETER | DESCRIPTION |
|---|---|
func
|
The function that the action will call.
TYPE:
|
as_passthrough
|
If True, we will pretend we're returning a function.
This is useful if you use the
TYPE:
|
desc
|
Description of the action function. If None, the docstring of the function will be used.
TYPE:
|
override_type_hint_for_llm
|
If True, the type hints of the function will be ignored and replaced by a more LLM-friendly version.
TYPE:
|
suppress_strict_mode_warning
|
If True, the warning about strict mode will be suppressed.
TYPE:
|
passive
|
If
TYPE:
|
hide_if_computer_use_mode
|
If
TYPE:
|
force_update_on
|
Name(s) of the input variable(s) that will be
checked for changes. For instance, if you have an action that
modifies a browser, but the browser is not explicitly returned by
the action, the |
| RETURNS | DESCRIPTION |
|---|---|
TypedAction[P, R] | Callable[[Callable[P, R]], TypedAction[P, R]] | Callable[[Callable[P, R]], Callable[P, R]]
|
If |
TypedAction[P, R] | Callable[[Callable[P, R]], TypedAction[P, R]] | Callable[[Callable[P, R]], Callable[P, R]]
|
returns an |
TypedAction[P, R] | Callable[[Callable[P, R]], TypedAction[P, R]] | Callable[[Callable[P, R]], Callable[P, R]]
|
subclass. |
| RAISES | DESCRIPTION |
|---|---|
TypeError
|
If the |
Source code in conatus/actions/decorators.py
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 | |
typeify
¶
typeify(
func: Callable[Concatenate[X, Ps], R],
) -> TypedAction[Ps, R]
Utility to tell mypy or pyright the type hints of an Action.
This really should be used only if you are struggling or annoyed by type
checkers not recognizing the type hints of your Action, and in particular
not correctly inferring the return type of the action function.
Note
When to use this function:
- For
pyright: when you've defined a subclass ofAction. If you've defined a subclass ofTypedAction, this should not be necessary.
- For
mypy: when you've defined a subclass ofActionorTypedAction.
Why not the entire Action class, you may ask? This has to do with the
type hinting. Only by passing the action function itself will mypy be able
to see its arguments and return types. It's not something it can see from
the class itself.
from conatus.actions.action import Action, TypedAction
from conatus.actions.decorators import typeify
from typing import Concatenate
# The emojis indicate whether the type checkers recognize the right types
class MyAction(Action):
@Action.function
def my_action(self, a: int, b: int) -> int:
return a + b
result = MyAction(1, 2) # Pyright: 👎, mypy: 👎
typeified = typeify(MyAction.my_action)(1, 2) # Pyright: ✅, mypy: ✅
class MyTypedAction(TypedAction[[int,int], int]):
@Action.function
def now_typed(self, a: int, b: int) -> int:
return a + b
result = MyTypedAction(1, 2) # Pyright: ✅, mypy: 👎
typeified = typeify(MyTypedAction.now_typed)(1, 2) # Pyright: ✅, mypy: ✅
Warning
This function returns an instance of TypedAction, not a class.
Most of the time, you won't notice or care, but this might be a
cause for bugs.
| PARAMETER | DESCRIPTION |
|---|---|
func
|
The action function (not the class!)
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
TypedAction[Ps, R]
|
An instance of the |
TypedAction[Ps, R]
|
type hints. |
| RAISES | DESCRIPTION |
|---|---|
TypeError
|
If the function is not part of an |
TypeError
|
If the callable is not a function. |
Source code in conatus/actions/decorators.py
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 | |
termination_action
¶
termination_action(
action: Action,
expected_outputs: OrderedDict[
str, tuple[TypeOfType, str]
],
) -> Action
Decorator to mark an action as a termination action.
This means that we replace all of the input parameters of the action with the expected outputs of the run (or recipe).
Note that at least one of the expected outputs must be a bool named
"success".
| PARAMETER | DESCRIPTION |
|---|---|
action
|
The action to mark as a termination action.
TYPE:
|
expected_outputs
|
The expected outputs of the run (or recipe). The keys are the names of the outputs, and the values are a tuple containing the type of the output and its description. The inputs of the action will be replaced by these outputs.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Action
|
The action with the inputs replaced by the expected outputs. |
Source code in conatus/actions/decorators.py
convert_to_action
¶
convert_to_action(
raw_action: Action | ActionBlueprint | FunctionType,
) -> Action
Convert a raw action to an action.
| PARAMETER | DESCRIPTION |
|---|---|
raw_action
|
The raw action to convert.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Action
|
The action. |