Added many tools
This commit is contained in:
178
tools/agent_loop.py
Normal file
178
tools/agent_loop.py
Normal file
@@ -0,0 +1,178 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from core.tools.registry import registry
|
||||
from core.events import bus
|
||||
|
||||
|
||||
class AgentLoop:
|
||||
"""
|
||||
Minimal deterministic agent loop.
|
||||
|
||||
Orchestrates tools like:
|
||||
- search
|
||||
- intelligent_search
|
||||
- crawler
|
||||
- research
|
||||
|
||||
Can later be upgraded with LLM-based planning.
|
||||
"""
|
||||
|
||||
def __init__(self, ctx):
|
||||
self.ctx = ctx
|
||||
self.max_steps = 5
|
||||
|
||||
# =========================
|
||||
# ENTRY POINT
|
||||
# =========================
|
||||
|
||||
def run(self, goal: str) -> dict[str, Any]:
|
||||
state = {
|
||||
"goal": goal,
|
||||
"steps": [],
|
||||
"memory": [],
|
||||
"final": None
|
||||
}
|
||||
|
||||
bus.log(
|
||||
"AGENT",
|
||||
"agent_loop_start",
|
||||
"INFO",
|
||||
{"goal": goal}
|
||||
)
|
||||
|
||||
for step in range(self.max_steps):
|
||||
action = self._decide(state)
|
||||
|
||||
if action["type"] == "stop":
|
||||
state["final"] = action.get("result")
|
||||
break
|
||||
|
||||
result = self._execute(action, state)
|
||||
state["steps"].append(action)
|
||||
state["memory"].append(result)
|
||||
|
||||
# simple convergence heuristic
|
||||
if self._is_satisfied(state):
|
||||
state["final"] = result
|
||||
break
|
||||
|
||||
if not state["final"]:
|
||||
state["final"] = state["memory"][-1] if state["memory"] else {}
|
||||
|
||||
return state
|
||||
|
||||
# =========================
|
||||
# DECISION LOGIC (RULE-BASED FOR NOW)
|
||||
# =========================
|
||||
|
||||
def _decide(self, state: dict[str, Any]) -> dict[str, Any]:
|
||||
"""
|
||||
Very simple heuristic planner.
|
||||
|
||||
Later upgrade point: replace with LLM planner.
|
||||
"""
|
||||
|
||||
goal = state["goal"]
|
||||
memory = state["memory"]
|
||||
|
||||
if not memory:
|
||||
return {
|
||||
"type": "tool",
|
||||
"tool": "research",
|
||||
"input": {
|
||||
"query": goal,
|
||||
"depth": 1
|
||||
}
|
||||
}
|
||||
|
||||
last = memory[-1]
|
||||
|
||||
# if research returned sources, refine or stop
|
||||
if isinstance(last, dict) and "sources" in last:
|
||||
if len(last["sources"]) >= 2:
|
||||
return {
|
||||
"type": "stop",
|
||||
"result": last
|
||||
}
|
||||
|
||||
# if weak results, deepen search
|
||||
return {
|
||||
"type": "tool",
|
||||
"tool": "research",
|
||||
"input": {
|
||||
"query": goal,
|
||||
"depth": 2,
|
||||
"max_sources": 5
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
"type": "stop",
|
||||
"result": last
|
||||
}
|
||||
|
||||
# =========================
|
||||
# TOOL EXECUTION
|
||||
# =========================
|
||||
|
||||
def _execute(self, action: dict[str, Any], state: dict[str, Any]) -> Any:
|
||||
tool_name = action.get("tool")
|
||||
tool_input = action.get("input", {})
|
||||
|
||||
bus.log(
|
||||
"AGENT",
|
||||
"agent_tool_call",
|
||||
"INFO",
|
||||
{
|
||||
"tool": tool_name,
|
||||
"input": tool_input
|
||||
}
|
||||
)
|
||||
|
||||
if not tool_name:
|
||||
return {"error": "No tool specified"}
|
||||
|
||||
try:
|
||||
result = registry.run(
|
||||
tool_name,
|
||||
tool_input,
|
||||
self.ctx
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
return {
|
||||
"error": str(e),
|
||||
"tool": tool_name
|
||||
}
|
||||
|
||||
# =========================
|
||||
# STOPPING CONDITION
|
||||
# =========================
|
||||
|
||||
def _is_satisfied(self, state: dict[str, Any]) -> bool:
|
||||
"""
|
||||
Simple satisfaction heuristic.
|
||||
|
||||
Later upgrade: LLM-based evaluation.
|
||||
"""
|
||||
|
||||
memory = state["memory"]
|
||||
|
||||
if not memory:
|
||||
return False
|
||||
|
||||
last = memory[-1]
|
||||
|
||||
if isinstance(last, dict):
|
||||
# if research returned structured sources, assume OK
|
||||
if "sources" in last and len(last["sources"]) > 0:
|
||||
return True
|
||||
|
||||
if "error" in last:
|
||||
return True
|
||||
|
||||
return False
|
||||
Reference in New Issue
Block a user
