Tutorial: Simple Agent CLI (E01)¶
This tutorial corresponds to the example file examples/E01_simple_agent_cli.py
.
It demonstrates a basic command-line agent that does not use an LLM for tool selection. Instead, it shows how to:
- Configure the simple_keyword
command processor, which maps keywords like "calculate" or "weather" to specific tool IDs.
- Explicitly enable the calculator_tool
and open_weather_map_tool
in tool_configurations
.
- Use genie.run_command()
to process user input. The keyword processor will find the tool and then prompt the user for the necessary parameters.
Example Code¶
examples/E01_simple_agent_cli.py¶
""" Example: Simple Agent CLI (Refactored for Genie Facade)
This example demonstrates a basic command-line agent that uses the Genie facade to interact with tools, configured via FeatureSettings.
To Run:
1. Ensure Genie Tooling is installed (poetry install --all-extras
).
2. Set an environment variable for OpenWeatherMap API key if you want to test that tool:
export OPENWEATHERMAP_API_KEY="your_actual_key"
3. Run from the root of the project:
poetry run python examples/E01_simple_agent_cli.py
The agent will: - Initialize Genie with a simple keyword command processor. - Ask for your input (e.g., "calculate 10 + 5", "weather in London"). - Use genie.run_command() to process the input and execute the tool. - Display the result. """ import asyncio import json import logging import os from typing import Optional
from genie_tooling.config.features import FeatureSettings from genie_tooling.config.models import MiddlewareConfig from genie_tooling.genie import Genie
Genie uses EnvironmentKeyProvider by default if no key_provider_instance is given¶
and key_provider_id is not set or set to "env_keys" in MiddlewareConfig.¶
async def run_simple_agent_cli(): print("--- Simple Agent CLI (Genie Facade Version) ---")
# 1. Configure Middleware using FeatureSettings
app_config = MiddlewareConfig(
features=FeatureSettings(
llm="none", # Using simple_keyword, no LLM needed for command processing itself
command_processor="simple_keyword",
# No RAG or complex tool lookup needed for this basic CLI
rag_embedder="none",
tool_lookup="none",
),
# Configure the simple_keyword_processor
command_processor_configurations={
"simple_keyword_processor_v1": { # Canonical ID
"keyword_map": {
"calculate": "calculator_tool",
"math": "calculator_tool",
"add": "calculator_tool",
"plus": "calculator_tool",
"weather": "open_weather_map_tool",
"forecast": "open_weather_map_tool",
},
"keyword_priority": ["calculate", "math", "add", "plus", "weather", "forecast"]
}
},
tool_configurations={
# Explicitly enable the tools to be used
"calculator_tool": {},
"open_weather_map_tool": {}
# No specific config needed for these tools if API keys are handled
# by the default EnvironmentKeyProvider.
}
)
# 2. Instantiate Genie
genie: Optional[Genie] = None
try:
print("\nInitializing Genie facade...")
# No key_provider_instance needed if using EnvironmentKeyProvider (default)
genie = await Genie.create(config=app_config)
print("Genie facade initialized successfully!")
# 3. CLI Loop
print("\nType 'quit' to exit.")
if not os.getenv("OPENWEATHERMAP_API_KEY"):
print("Note: OPENWEATHERMAP_API_KEY not set. 'weather' commands will select the tool but execution will fail.")
while True:
try:
user_query = await asyncio.to_thread(input, "\n> Your query: ")
except KeyboardInterrupt:
print("\nExiting...")
break
if user_query.lower() == "quit":
print("Exiting...")
break
if not user_query.strip():
continue
print(f"Processing command: '{user_query}'")
try:
# genie.run_command will use the configured 'simple_keyword_processor_v1'
# which will prompt for parameters if a tool is matched.
command_result = await genie.run_command(user_query)
print("\nCommand Result:")
if command_result:
print(json.dumps(command_result, indent=2, default=str))
if command_result.get("tool_result") and command_result["tool_result"].get("error_message"):
print(f"Tool Execution Error: {command_result['tool_result']['error_message']}")
elif command_result.get("error"):
print(f"Command Processing Error: {command_result['error']}")
else:
print("Command did not produce a result.")
except Exception as e:
print(f"An error occurred while processing the command: {e}")
logging.exception("Error details:")
except Exception as e:
print(f"Failed to initialize or run agent: {e}")
logging.exception("Initialization/runtime error details:")
finally:
if genie:
print("\nTearing down Genie facade...")
await genie.close()
print("Genie facade torn down.")
if name == "main": logging.basicConfig(level=logging.INFO) # For more detailed library logs: # logging.getLogger("genie_tooling").setLevel(logging.DEBUG) asyncio.run(run_simple_agent_cli())