Skip to content

Agentic AI & Tools

Build AI agents that can use tools and reason through problems.

Prerequisites


Regular LLMs can only generate text. Agentic AI can:

  • Use tools (functions you define)
  • Reason about which tools to use
  • Iterate until the task is complete
User: "What's the weather in Tokyo?"
Regular LLM: Agentic LLM:
"I don't have 1. I need weather data
real-time 2. Call get_weather("Tokyo")
data..." 3. Return: "It's 22°C and sunny"

Define functions the LLM can use:

import from byllm.lib { Model }
glob llm = Model(model_name="gpt-4o-mini");
# Define a tool
def get_current_time() -> str {
import datetime;
return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S");
}
# LLM function that can use the tool
def answer(question: str) -> str by llm(
tools=[get_current_time]
);
with entry {
response = answer("What time is it right now?");
print(response);
}

Output:

The current time is 2024-01-21 14:30:45.

The LLM automatically:

  1. Recognized it needed the current time
  2. Called get_current_time()
  3. Used the result to form its answer

import from byllm.lib { Model }
glob llm = Model(model_name="gpt-4o-mini");
def add(a: int, b: int) -> int {
return a + b;
}
def multiply(a: int, b: int) -> int {
return a * b;
}
def get_pi() -> float {
return 3.14159;
}
def solve_math(problem: str) -> str by llm(
tools=[add, multiply, get_pi]
);
with entry {
print(solve_math("What is 5 + 3?"));
print(solve_math("Calculate 7 times 8"));
print(solve_math("What is pi times 2?"));
}

Tools can have parameters that the LLM fills in:

import from byllm.lib { Model }
glob llm = Model(model_name="gpt-4o-mini");
"""Search the database for matching records."""
def search_database(query: str, limit: int = 10) -> list[str] {
# Simulated database search
return [f"Result {i} for '{query}'" for i in range(min(limit, 3))];
}
"""Get information about a specific user."""
def get_user_info(user_id: str) -> dict {
# Simulated user lookup
return {
"id": user_id,
"name": f"User {user_id}",
"email": f"user{user_id}@example.com"
};
}
def query(question: str) -> str by llm(
tools=[search_database, get_user_info]
);
with entry {
print(query("Find records about 'machine learning'"));
print(query("What's the email for user 42?"));
}

ReAct (Reason + Act) lets the LLM think step-by-step:

import from byllm.lib { Model }
glob llm = Model(model_name="gpt-4o");
"""Search the web for information."""
def search_web(query: str) -> str {
# Simulated web search
return f"Web results for '{query}': Found relevant information about the topic.";
}
"""Evaluate a mathematical expression."""
def calculate(expression: str) -> float {
return eval(expression);
}
"""Get today's date."""
def get_date() -> str {
import datetime;
return datetime.date.today().isoformat();
}
def research(question: str) -> str by llm(
tools=[search_web, calculate, get_date]
);
sem research = "Answer complex questions using reasoning and tools.";
with entry {
answer = research(
"If today's date has an odd day number, calculate 2^10, "
"otherwise calculate 3^5"
);
print(answer);
}

With ReAct, the LLM:

  1. Thought: I need to check today’s date first
  2. Action: Call get_date()
  3. Observation: 2024-01-21 (day 21 is odd)
  4. Thought: Since it’s odd, I need to calculate 2^10
  5. Action: Call calculate("2**10")
  6. Observation: 1024
  7. Answer: The result is 1024

Tools can be methods on objects:

import from byllm.lib { Model }
glob llm = Model(model_name="gpt-4o-mini");
obj Calculator {
has memory: float = 0;
"""Add to memory."""
def add(x: float) -> float {
self.memory += x;
return self.memory;
}
"""Subtract from memory."""
def subtract(x: float) -> float {
self.memory -= x;
return self.memory;
}
"""Clear memory."""
def clear() -> float {
self.memory = 0;
return self.memory;
}
"""Get current memory value."""
def get_memory() -> float {
return self.memory;
}
def calculate(instructions: str) -> str by llm(
tools=[self.add, self.subtract, self.clear, self.get_memory]
);
}
sem Calculator.calculate = "Perform calculations step by step.";
with entry {
calc = Calculator();
result = calc.calculate("Start at 0, add 10, subtract 3, then add 5");
print(result);
print(f"Final memory: {calc.memory}");
}

Combine tools with graph traversal:

import from byllm.lib { Model }
glob llm = Model(model_name="gpt-4o-mini");
node Document {
has title: str;
has content: str;
has summary: str = "";
}
def summarize(content: str) -> str by llm();
sem summarize = "Summarize this document in 2-3 sentences.";
"""Search documents for matching content."""
def search_documents(query: str, docs: list) -> list {
results = [];
for doc in docs {
if query.lower() in doc.content.lower() {
results.append(doc.title);
}
}
return results;
}
walker DocumentAgent {
has query: str;
can process with Root entry {
all_docs = [-->](?:Document);
# Find relevant documents
relevant = search_documents(self.query, all_docs);
# Summarize each relevant document
for doc in all_docs {
if doc.title in relevant {
doc.summary = summarize(doc.content);
report {"title": doc.title, "summary": doc.summary};
}
}
}
}
with entry {
root ++> Document(
title="AI Overview",
content="Artificial intelligence is transforming industries..."
);
root ++> Document(
title="Weather Report",
content="Sunny skies expected throughout the week..."
);
root ++> Document(
title="Machine Learning Guide",
content="Machine learning is a subset of AI that..."
);
result = root spawn DocumentAgent(query="AI");
for doc in result.reports {
print("## " + doc["title"]);
print(doc["summary"]);
print();
}
}

Provide additional context to the LLM:

import from byllm.lib { Model }
glob llm = Model(model_name="gpt-4o-mini");
glob company_info = """
Company: TechCorp
Products: CloudDB, SecureAuth, DataViz
Support Hours: 9 AM - 5 PM EST
Support Email: support@techcorp.com
""";
def support_agent(question: str) -> str by llm(
incl_info={"company_context": company_info}
);
sem support_agent = "Answer customer questions about our products and services.";
with entry {
print(support_agent("What products do you offer?"));
print(support_agent("What are your support hours?"));
}

import from byllm.lib { Model }
import json;
glob llm = Model(model_name="gpt-4o");
# Knowledge base
glob kb: dict = {
"products": ["Widget A", "Widget B", "Service X"],
"prices": {"Widget A": 99, "Widget B": 149, "Service X": 29},
"inventory": {"Widget A": 50, "Widget B": 0, "Service X": 999}
};
"""List all available products."""
def list_products() -> list[str] {
return kb["products"];
}
"""Get the price of a product."""
def get_price(product: str) -> str {
if product in kb["prices"] {
return f"${kb['prices'][product]}";
}
return "Product not found";
}
"""Check if a product is in stock."""
def check_inventory(product: str) -> str {
if product in kb["inventory"] {
qty = kb["inventory"][product];
if qty > 0 {
return f"In stock ({qty} available)";
}
return "Out of stock";
}
return "Product not found";
}
"""Place an order for a product."""
def place_order(product: str, quantity: int) -> str {
if product not in kb["inventory"] {
return "Product not found";
}
if kb["inventory"][product] < quantity {
return "Insufficient inventory";
}
kb["inventory"][product] -= quantity;
return f"Order placed: {quantity}x {product}";
}
def sales_agent(request: str) -> str by llm(
tools=[list_products, get_price, check_inventory, place_order]
);
sem sales_agent = "Browse products, check prices and availability, and place orders.";
with entry {
print("Customer: What products do you have?");
print(f"Agent: {sales_agent('What products do you have?')}");
print();
print("Customer: How much is Widget A and is it in stock?");
print(f"Agent: {sales_agent('How much is Widget A and is it in stock?')}");
print();
print("Customer: I'd like to order 2 Widget A please");
print(f"Agent: {sales_agent('I want to order 2 Widget A')}");
}

ConceptUsage
Tools (ReAct reasoning)by llm(tools=[func1, func2])
Object methods as toolsby llm(tools=[self.method])
Context injectionby llm(incl_info={"key": value})
sem on toolsHelp LLM understand when to use tools

  1. Clear sem declarations - The LLM uses sem descriptions to understand tools
  2. Descriptive parameters - Name parameters clearly
  3. Return useful info - Return strings the LLM can interpret
  4. Limit tool count - Too many tools can confuse the LLM
  5. Use ReAct for complex tasks - Multi-step reasoning