Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions agents/official/beeai-framework/chat/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ authors = [
]
requires-python = ">=3.13,<4"
dependencies = [
"beeai-framework[duckduckgo,wikipedia]~=0.1.34",
"beeai-framework[duckduckgo,wikipedia]~=0.1.35",
"beeai-sdk",
"openinference-instrumentation-beeai>=0.1.6",
"openinference-instrumentation-beeai>=0.1.7",
"pydantic-settings>=2.9.0",
"sqlalchemy>=2.0.41",
"uvicorn>=0.35.0",
Expand Down
73 changes: 58 additions & 15 deletions agents/official/beeai-framework/chat/src/chat/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@
)
from beeai_framework.agents.experimental.utils._tool import FinalAnswerTool
from beeai_framework.backend.types import ChatModelParameters
from beeai_framework.emitter import EventMeta
from beeai_framework.memory import UnconstrainedMemory
from beeai_framework.middleware.trajectory import GlobalTrajectoryMiddleware
from beeai_framework.tools import Tool
from beeai_framework.tools.search.duckduckgo import DuckDuckGoSearchTool
from beeai_framework.tools.search.wikipedia import WikipediaTool
from beeai_framework.tools.weather.openmeteo import OpenMeteoTool

from beeai_framework.tools.weather import OpenMeteoTool

from beeai_sdk.a2a.extensions import (
AgentDetail,
Expand All @@ -42,6 +44,7 @@
from beeai_sdk.a2a.types import AgentMessage
from beeai_sdk.server import Server
from beeai_sdk.server.context import Context
from chat.tools.general.current_time import CurrentTimeTool
from chat.helpers.citations import extract_citations
from chat.helpers.trajectory import TrajectoryContent
from openinference.instrumentation.beeai import BeeAIInstrumentor
Expand All @@ -58,12 +61,18 @@
ClarificationTool,
clarification_tool_middleware,
)
from chat.tools.general.current_time import CurrentTimeTool

# Temporary instrument fix
EventMeta.model_fields["context"].exclude = True

BeeAIInstrumentor().instrument()
## TODO: https://github.com/phoenixframework/phoenix/issues/6224
logging.getLogger("opentelemetry.exporter.otlp.proto.http._log_exporter").setLevel(logging.CRITICAL)
logging.getLogger("opentelemetry.exporter.otlp.proto.http.metric_exporter").setLevel(logging.CRITICAL)
logging.getLogger("opentelemetry.exporter.otlp.proto.http._log_exporter").setLevel(
logging.CRITICAL
)
logging.getLogger("opentelemetry.exporter.otlp.proto.http.metric_exporter").setLevel(
logging.CRITICAL
)

logger = logging.getLogger(__name__)

Expand All @@ -87,13 +96,36 @@
user_greeting="How can I help you?",
tools=[
AgentDetailTool(
name="Web Search (DuckDuckGo)",
description="Retrieves real-time search results.",
name="Act Tool",
description="Auxiliary tool that ensures thoughtful tool selection by requiring explicit reasoning and tool choice before executing any other tool.",
),
AgentDetailTool(
name="Clarification Tool",
description="Enables the agent to ask clarifying questions when user requirements are unclear, preventing assumptions and ensuring accurate task completion.",
),
AgentDetailTool(
name="Wikipedia Search",
description="Fetches summaries and information from Wikipedia articles.",
),
AgentDetailTool(name="Wikipedia Search", description="Fetches summaries from Wikipedia."),
AgentDetailTool(
name="Weather Information (OpenMeteo)",
description="Provides real-time weather updates.",
description="Provides real-time weather updates and forecasts.",
),
AgentDetailTool(
name="Web Search (DuckDuckGo)",
description="Retrieves real-time search results from the web.",
),
AgentDetailTool(
name="File Reader",
description="Reads and returns content from uploaded or generated files.",
),
AgentDetailTool(
name="File Creator",
description="Creates new files with specified content and metadata, uploading them to the platform for download or further processing.",
),
AgentDetailTool(
name="Current Time",
description="Provides current date and time information.",
),
],
framework="BeeAI",
Expand Down Expand Up @@ -130,7 +162,9 @@
"""
),
tags=["chat"],
examples=["Please find a room in LA, CA, April 15, 2025, checkout date is april 18, 2 adults"],
examples=[
"Please find a room in LA, CA, April 15, 2025, checkout date is april 18, 2 adults"
],
)
],
)
Expand All @@ -144,7 +178,9 @@ async def chat(
The agent is an AI-powered conversational system with memory, supporting real-time search, Wikipedia lookups,
and weather updates through integrated tools.
"""
extracted_files = await extract_files(history=messages[context.context_id], incoming_message=message)
extracted_files = await extract_files(
history=messages[context.context_id], incoming_message=message
)
input = to_framework_message(message)

# Configure tools
Expand All @@ -154,12 +190,12 @@ async def chat(

FinalAnswerTool.description = """Assemble and send the final answer to the user. When using information gathered from other tools that provided URL addresses, you MUST properly cite them using markdown citation format: [description](URL).

Citation Requirements:
# Citation Requirements:
- Use descriptive text that summarizes the source content
- Include the exact URL provided by the tool
- Place citations inline where the information is referenced

Examples:
# Examples:
- According to [OpenAI's latest announcement](https://example.com/gpt5), GPT-5 will be released next year.
- Recent studies show [AI adoption has increased by 67%](https://example.com/ai-study) in enterprise environments.
- Weather data indicates [temperatures will reach 25°C tomorrow](https://weather.example.com/forecast).""" # type: ignore
Expand All @@ -186,6 +222,7 @@ async def chat(
api_key=os.getenv("LLM_API_KEY", "dummy"),
base_url=os.getenv("LLM_API_BASE", "http://localhost:11434/v1"),
parameters=ChatModelParameters(temperature=0.0),
tool_choice_support=set(),
)

# Create agent
Expand All @@ -195,7 +232,7 @@ async def chat(
memory=UnconstrainedMemory(),
requirements=requirements,
middlewares=[
GlobalTrajectoryMiddleware(included=[Tool]),
GlobalTrajectoryMiddleware(included=[Tool]), # ChatModel,
act_tool_middleware,
clarification_tool_middleware,
],
Expand Down Expand Up @@ -253,14 +290,20 @@ async def chat(

message = AgentMessage(
text=clean_text,
metadata=(citation.citation_metadata(citations=citations) if citations else None),
metadata=(
citation.citation_metadata(citations=citations) if citations else None
),
)
messages[context.context_id].append(message)
yield message


def serve():
server.run(host=os.getenv("HOST", "127.0.0.1"), port=int(os.getenv("PORT", 8000)), configure_telemetry=True)
server.run(
host=os.getenv("HOST", "127.0.0.1"),
port=int(os.getenv("PORT", 8000)),
configure_telemetry=True,
)


if __name__ == "__main__":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class FileCreatorTool(
Creates a new file and writes the provided content into it.
"""

name: str = "FileCreator"
name: str = "file_creator"
description: str = "Create a new file with the specified content."
input_schema: type[FileCreatorInput] = FileCreatorInput

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from beeai_framework.context import RunContext
from beeai_framework.emitter import Emitter, EventMeta
from beeai_framework.tools import (
AnyTool,
JSONToolOutput,
Tool,
ToolInputValidationError,
Expand Down Expand Up @@ -139,9 +140,16 @@ class ActAlwaysFirstRequirement(Requirement[RequirementAgentRunState]):

name: str = "act_always_first"

tools: list[AnyTool] = []

async def init(self, *, tools: list[AnyTool], ctx: RunContext) -> None:
await super().init(tools=tools, ctx=ctx)
self.tools = tools

@run_with_context
async def run(self, state: RequirementAgentRunState, ctx: RunContext) -> list[Rule]:
last_step = state.steps[-1] if state.steps else None

if last_step and last_step.tool and last_step.tool.name == "act":
assert isinstance(last_step.tool, ActTool)
if last_step.error is not None:
Expand Down Expand Up @@ -172,14 +180,27 @@ async def run(self, state: RequirementAgentRunState, ctx: RunContext) -> list[Ru
)
]

# Hide all tools except ActTool on the first step
rules = [
Rule(
target=t.name,
hidden=True,
allowed=False,
prevent_stop=False,
forced=False,
)
for t in self.tools
if not isinstance(t, ActTool)
]
return [
Rule(
target="act",
forced=True,
allowed=True,
prevent_stop=False,
hidden=False,
)
),
*rules,
]


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class CurrentTimeTool(Tool[CurrentTimeToolInput]):
def input_schema(self) -> type[CurrentTimeToolInput]:
return CurrentTimeToolInput

def _run(
async def _run(
self,
input: CurrentTimeToolInput,
options: ToolRunOptions | None,
Expand Down
Loading