Using predefined skills

Other tasks may require providing an agent with predefined skills for being able to solve them more efficiently or to solve them at all. For example, the freeact_skills.zotero.api skill module from the freeact-skills project provides a Python API for syncing Zotero Group libraries with a local directory, loading collection and document metadata as graph into memory and navigating it.

The entire freeact_skills.zotero package is partitioned into a freeact_skills.zotero.api module that provides the Python API, including a definition of domain classes. This module is presented to code action models so they can understand how to use the Zotero skill. The freeact_skills.zotero.impl module contains further implementation details that need not be presented to code action models.

The following example demonstrates how a freeact agent uses that skill. It demonstrates how multiple methods and functions from the skill module can be flexibly combined within code actions. The freeact_skills.zotero.api module is also a good example how domain objects may encapsulate both data and behavior - a core principle of object-oriented programming. A Collection object, for example, encapsulates data and provides methods sub_documents() and sub_collections() to recursively traverse the collection and document graph under it.

import asyncio
import os

from rich.console import Console

from freeact import CodeActAgent, LiteCodeActModel, execution_environment
from freeact.cli.utils import stream_conversation


async def main():
    async with execution_environment(
        ipybox_tag="ghcr.io/gradion-ai/ipybox:example",
        ipybox_env={
            "ZOTERO_API_KEY": os.environ["ZOTERO_API_KEY"],
            "ZOTERO_GROUP_ID": os.environ["ZOTERO_GROUP_ID"],
        },
    ) as env:
        async with env.code_provider() as provider:
            skill_sources = await provider.get_sources(
                module_names=["freeact_skills.zotero.api"],
            )
        async with env.code_executor() as executor:
            model = LiteCodeActModel(
                model_name="anthropic/claude-3-7-sonnet-20250219",
                reasoning_effort="low",
                skill_sources=skill_sources,
                api_key=os.getenv("ANTHROPIC_API_KEY"),
            )
            agent = CodeActAgent(model=model, executor=executor)
            await stream_conversation(agent, console=Console())


if __name__ == "__main__":
    asyncio.run(main())
.env
ZOTERO_API_KEY=...
ZOTERO_GROUP_ID=...
uvx freeact \
  --ipybox-tag=ghcr.io/gradion-ai/ipybox:example \
  --model-name=anthropic/claude-3-7-sonnet-20250219 \
  --reasoning-effort=low \
  --skill-modules=freeact_skills.zotero.api \
  --api-key=$ANTHROPIC_API_KEY

Example

output