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())