Basic usage
A freeact
agent system consists of:
- A code execution Docker container, managed by the
CodeExecutionContainer
context manager. This tutorial uses thegradion-ai/ipybox-example
image. - A code executor, managed by the
CodeExecutor
context manager. It manages an IPython kernel's lifecycle within the container and handles code execution. - A code action model that generates code actions to be executed by the executor. Models must implement the interfaces defined in the
freeact.model
package. This tutorial usesClaude
, configured withclaude-3-5-sonnet-20241022
as model name. - A
CodeActAgent
configured with both the model and executor. It orchestrates their interaction until a final response is ready.
import asyncio
import os
from dotenv import load_dotenv
from freeact import (
Claude,
CodeActAgent,
CodeExecutionContainer,
CodeExecutor,
)
from freeact.examples.utils import stream_conversation
from freeact.logger import Logger
async def main():
api_keys = {
"ANTHROPIC_API_KEY": os.environ["ANTHROPIC_API_KEY"],
"GOOGLE_API_KEY": os.environ["GOOGLE_API_KEY"],
}
async with CodeExecutionContainer(
tag="ghcr.io/gradion-ai/ipybox:example", # (2)!
env=api_keys,
workspace_path="workspace", # (3)!
) as container:
async with CodeExecutor(
key="example", # (4)!
port=container.port, # (5)!
workspace=container.workspace,
) as executor:
skill_sources = await executor.get_module_sources(
["freeact_skills.search.google.stream.api"], # (6)!
)
async with Logger(file="logs/agent.log") as logger: # (7)!
model = Claude(model_name="claude-3-5-sonnet-20241022", logger=logger)
agent = CodeActAgent(model=model, executor=executor)
await stream_conversation(agent, skill_sources=skill_sources) # (1)!
if __name__ == "__main__":
load_dotenv()
asyncio.run(main())
-
freeact/examples/utils.py::stream_conversation
async def stream_conversation(agent: CodeActAgent, **kwargs): while True: user_message = await ainput("User message: ('q' to quit) ") if user_message.lower() == "q": break agent_turn = agent.run(user_message, **kwargs) await stream_turn(agent_turn) async def stream_turn(agent_turn: CodeActAgentTurn): produced_images: Dict[Path, Image.Image] = {} async for activity in agent_turn.stream(): match activity: case CodeActModelTurn() as turn: print("Agent response:") async for s in turn.stream(): print(s, end="", flush=True) print() response = await turn.response() if response.code: print("\n```python") print(response.code) print("```\n") case CodeExecution() as execution: print("Execution result:") async for s in execution.stream(): print(s, end="", flush=True) result = await execution.result() produced_images.update(result.images) print() if produced_images: print("\n\nProduced images:") for path in produced_images.keys(): print(str(path))
-
Tag of the
ipybox
Docker image. -
Path to the workspace directory on the host machine. This directory enables sharing custom skills modules between the container and host machine (see Skill development tutorial).
-
Key for this executor's private workspace directories:
workspace/skills/private/example
: Private skills and working directoryworkspace/images/example
: Directory for storing produced images
-
Container host port. Automatically allocated by
CodeExecutionContainer
but can be manually specified. -
Skill modules on the
executor
's Python path that can be resolved to their source code and metadata. This information is included in the code actionmodel
's context. -
A contextual
Logger
for recording messages and metadata.
A CodeActAgent
can engage in multi-turn conversations with a user. Each turn is initiated using the agent's run
method. We use the stream_conversation
(1) helper function to run
the agent and stream the output from both the agent's model and code executor to stdout
.
- freeact/examples/utils.py::stream_conversation
async def stream_conversation(agent: CodeActAgent, **kwargs): while True: user_message = await ainput("User message: ('q' to quit) ") if user_message.lower() == "q": break agent_turn = agent.run(user_message, **kwargs) await stream_turn(agent_turn) async def stream_turn(agent_turn: CodeActAgentTurn): produced_images: Dict[Path, Image.Image] = {} async for activity in agent_turn.stream(): match activity: case CodeActModelTurn() as turn: print("Agent response:") async for s in turn.stream(): print(s, end="", flush=True) print() response = await turn.response() if response.code: print("\n```python") print(response.code) print("```\n") case CodeExecution() as execution: print("Execution result:") async for s in execution.stream(): print(s, end="", flush=True) result = await execution.result() produced_images.update(result.images) print() if produced_images: print("\n\nProduced images:") for path in produced_images.keys(): print(str(path))
This tutorial uses the freeact_skills.search.google.stream.api
skill module from the freeact-skills
project to process queries that require internet searches. This module provides generative Google search capabilities powered by the Gemini 2 API.
The skill module's source code is obtained from the executor
and passed to the model through the agent's run
method. Other model implementations may require skill module sources to be passed through their constructor instead.
Setup
Install freeact
with:
The tutorials require an ANTHROPIC_API_KEY
for the Claude API and a GOOGLE_API_KEY
for the Gemini 2 API. You can get them from Anthropic Console and Google AI Studio. Add them to a .env
file in the current working directory:
The tutorials use the pre-built ghcr.io/gradion-ai/ipybox:example
Docker image for sandboxed code execution.
Running
The Python example above is part of the freeact
package and can be run with:
For formatted and colored console output, as shown in the example conversation, you can use the freeact
CLI:
python -m freeact.cli \
--model-name=claude-3-5-sonnet-20241022 \
--ipybox-tag=ghcr.io/gradion-ai/ipybox:example \
--executor-key=example \
--skill-modules=freeact_skills.search.google.stream.api
To use Gemini instead of Claude, run:
python -m freeact.cli \
--model-name=gemini-2.0-flash-exp \
--ipybox-tag=ghcr.io/gradion-ai/ipybox:example \
--executor-key=example \
--skill-modules=freeact_skills.search.google.stream.api
Example conversation
Produced images: