Skip to content

Actions

tl;dr

Actions are at the core of Conatus. They are essentially functions that are exposed to an AI to execute a Task .

At its most basic level, an Action is a function that is decorated with the @action decorator. While that function is transformed into an Action, it is still possible to call it as a function:

from conatus import action

@action
def get_square_root(x: int) -> int:
    return x ** 0.5

# This will work like a function!
assert get_square_root(4) == 2

ok

Why do Actions exist?

AI agents need to do more than just process text—they need to call functions to interact with the world, fetch information, or perform side effects. In Conatus, these agent-accessible functions are called Actions.

Problem solved by Actions

Imagine an agent tasked with planning your day. To actually do anything, it must call tools (like sending a message or fetching the weather)—but it can only use functions that you explicitly make available. Furthermore:

  • The LLM can't execute arbitrary code; it must pick from a bounded toolset.
  • The runtime must validate inputs and track what happens after each tool call.
  • The agent must be able to reason about what tools are available, what their inputs/outputs look like, and use them reliably.

Actions solve these problems by providing:

  • Controlled exposure: Only specific, opt-in functions are enabled for the agent.
  • Structured interfaces: Each action provides a JSON schema, documentation, and type checking.
  • Runtime tracking: Every invocation can be recorded, for debugging or replay.

How are Actions different from regular functions, LangChain Tools, or Autogen tools?

  • Plain Python functions: Are not tracked, checked, or described in a way an LLM can use or discover reliably.
  • LangChain Tools / Autogen Tools: Require arguments to be strictly JSON-serializable, limiting what you can pass (no in-memory DataFrames, browsers, etc.). They often treat tools as opaque black boxes.
  • Conatus Actions:
    • Allow passing by reference (for non-serializable objects) and by value (for anything JSON-serializable).
    • Make actions transparent (you can call them like functions).
    • Enable type-aware input/output validation, rich documentation, and support advanced agent workflows like stepwise recipes.