ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s

This commit is contained in:
2026-08-20 13:12:50 +00:00
commit b119135836
10275 changed files with 3284984 additions and 0 deletions
@@ -0,0 +1,2 @@
# coding: utf-8
# Copyright (c) 2025 inclusionAI.
@@ -0,0 +1,144 @@
from aworld.trace.server import get_trace_server
from aworld.trace.constants import RunType, SPAN_NAME_PREFIX_EVENT_AGENT
from aworld.trace.instrumentation import semconv
def _get_agent_show_name(span: dict):
agent_name_prefix = SPAN_NAME_PREFIX_EVENT_AGENT
name = span.get("name")
if name and name.startswith(agent_name_prefix):
name = name[len(agent_name_prefix):]
if name and '---' in name:
name = name.split('---', 1)[0]
return name
def _remove_span_detail(root_spans: list):
keys_to_keep = {'span_id', 'show_name', 'task_group_id', 'event_id'}
for span in root_spans:
keys_to_remove = [key for key in span.keys() if key not in keys_to_keep]
for key in keys_to_remove:
span.pop(key, None)
if 'children' in span:
_remove_span_detail(span['children'])
def _build_graph(root_spans: list):
nodes = []
edges = []
group_id_counter = 0
def __process_group_span(parent_spans, group_id, group_spans):
nonlocal group_id_counter
group_id_counter += 1
# add group node
group_node = {
'span_id': f'group_{group_id_counter}',
'group_id': group_id,
'show_name': 'Task Group'
}
nodes.append(group_node)
# add edges from parent_spans to group node
for parent_span in parent_spans:
edges.append({
'source': parent_span['span_id'],
'target': group_node['span_id']
})
# add edges from group node to children spans
last_spans = []
for child in group_spans:
edges.append({
'source': group_node['span_id'],
'target': child['span_id']
})
last_spans.extend(__process_span(child))
return last_spans
def __process_span(span):
nonlocal group_id_counter
nodes.append(span)
if 'children' in span:
groups = {}
for child in span['children']:
group_id = child.get('task_group_id', id(child))
if group_id not in groups:
groups[group_id] = []
groups[group_id].append(child)
last_spans = [span] # The leaf nodes of the current subtree
for group_id, group_spans in groups.items():
if len(group_spans) > 1:
parent_spans = last_spans
last_spans = __process_group_span(parent_spans, group_id, group_spans)
else:
child_span = group_spans[0]
# add edges from last_spans to child
for prev_node in last_spans:
edges.append({
'source': prev_node['span_id'],
'target': child_span['span_id']
})
last_spans = __process_span(child_span)
return last_spans
for span in root_spans:
__process_span(span)
return {
'nodes': nodes,
'edges': edges
}
def get_agent_flow(trace_id):
storage = get_trace_server().get_storage()
spans = storage.get_all_spans(trace_id)
spans_dict = {span.span_id: span.dict() for span in spans}
children_spans = []
filtered_spans = {}
for span_id, span in spans_dict.items():
if span.get('is_event', False) and span.get('run_type') == RunType.AGNET.value:
span['show_name'] = _get_agent_show_name(span)
span['event_id'] = span.get('attributes', {}).get('event.id')
filtered_spans[span_id] = span
sub_task_spans = []
for span in list(filtered_spans.values()):
skip_this_span = False
parent_id = span['parent_id'] if span['parent_id'] else None
while parent_id and parent_id not in filtered_spans:
parent_span = spans_dict.get(parent_id)
if parent_span and parent_span.get('run_type') == RunType.TASK.value:
if str(parent_span['attributes'].get(semconv.TASK_IS_SUB_TASK)).lower() == 'true':
sub_task_spans.append(span)
skip_this_span = True
break
else:
print(f"parent_span_name: {parent_span['name']}")
span['task_group_id'] = parent_span['attributes'].get(semconv.TASK_GROUP_ID)
parent_id = parent_span['parent_id'] if parent_span and parent_span['parent_id'] else None
if skip_this_span:
continue
if parent_id:
parent_span = filtered_spans.get(parent_id)
if not parent_span:
continue
if 'children' not in parent_span:
parent_span['children'] = []
parent_span['children'].append(span)
children_spans.append(span)
filtered_span_list = [span for span in filtered_spans.values() if span not in sub_task_spans]
root_spans = [span for span in filtered_span_list
if span not in children_spans]
data = _build_graph(root_spans)
_remove_span_detail(data["nodes"])
return data
@@ -0,0 +1,41 @@
import asyncio
import pytest
import aworld.trace as trace
from aworld.logs.util import logger
trace.configure()
async def async_handler(name):
async with trace.span("async_handler") as span:
logger.info(f"async_handler start {name}")
await asyncio.sleep(1)
logger.info(f"async_handler end {name}")
async def async_handler2(name):
span = trace.get_current_span()
logger.info(f"async_handler2 span: {span.get_trace_id()}")
logger.info(f"async_handler2 start {name}")
await asyncio.sleep(1)
logger.info(f"async_handler2 end {name}")
@pytest.mark.asyncio
async def test1():
logger.info(f"hello test1")
task = asyncio.create_task(async_handler('test1'))
# await task
logger.info(f"hello test1 end")
@pytest.mark.asyncio
async def test2():
async with trace.span("test2") as span:
logger.info(f"hello test2")
task = asyncio.create_task(async_handler2(
'test2'))
# await task
logger.info(f"hello test2 end")
@@ -0,0 +1,24 @@
import time
class TestClassA:
def classa_function_1(self):
print("classa_function_1")
def classa_function_2(self):
time.sleep(0.02)
print("classa_function_2")
def classa_function_3(self):
print("classa_function_3")
class TestClassB:
def classb_function_1(self):
time.sleep(0.02)
print("classb_function_1")
def classb_function_2(self):
a = TestClassA()
a.classa_function_1()
a.classa_function_2()
a.classa_function_3()
print("classb_function_2")
@@ -0,0 +1,54 @@
import os
import time
import threading
from aworld.trace.config import ObservabilityConfig
from aworld.trace.instrumentation.fastapi import instrument_fastapi
from aworld.trace.instrumentation.requests import instrument_requests
from aworld.logs.util import logger, trace_logger
import aworld.trace as trace
from aworld.utils.import_package import import_packages
import_packages(['fastapi', 'uvicorn']) # noqa
import fastapi # noqa
import uvicorn # noqa
os.environ["MONITOR_SERVICE_NAME"] = "otlp_example"
os.environ["ANT_OTEL_ENDPOINT"] = "https://antcollector.alipay.com/namespace/aworld/task/aworld/otlp/api/v1/metrics"
trace.configure(ObservabilityConfig(
metrics_provider="otlp",
metrics_backend="antmonitor"
))
instrument_fastapi()
instrument_requests()
app = fastapi.FastAPI()
@app.get("/api/hello")
async def hello():
return {"message": "Hello World"}
def invoke_api():
import requests
response = requests.get('http://127.0.0.1:7071/api/hello')
logger.info(f"invoke_api response={response.text}")
def main():
logger.info("main running")
with trace.span("test_fastapi") as span:
trace_logger.info("start invoke_api")
invoke_api()
# if __name__ == "__main__":
# server_thread = threading.Thread(
# target=lambda: uvicorn.run(app, host="0.0.0.0", port=7071),
# daemon=True
# )
# server_thread.start()
# time.sleep(1)
# main()
# server_thread.join()
@@ -0,0 +1,45 @@
import threading
import flask
from aworld.trace.instrumentation.flask import instrument_flask
from aworld.trace.instrumentation.requests import instrument_requests
from aworld.logs.util import logger, trace_logger
import aworld.trace as trace
import os
from aworld.trace.config import ObservabilityConfig
os.environ["MONITOR_SERVICE_NAME"] = "otlp_example"
os.environ["ANT_OTEL_ENDPOINT"] = "https://antcollector.alipay.com/namespace/aworld/task/aworld/otlp/api/v1/metrics"
trace.configure(ObservabilityConfig(
metrics_provider="otlp",
metrics_backend="antmonitor"
))
instrument_flask()
instrument_requests()
app = flask.Flask(__name__)
@app.route('/api/test')
def test():
return 'Hello, World!'
def invoke_api():
import requests
response = requests.get('http://localhost:7070/api/test')
logger.info(f"invoke_api response={response.text}")
def main():
logger.info("main running")
with trace.span("test_flask") as span:
trace_logger.info("start invoke_api")
invoke_api()
# if __name__ == "__main__":
# thread = threading.Thread(target=lambda: app.run(port=7070), daemon=True)
# thread.start()
# main()
# thread.join()
@@ -0,0 +1,25 @@
import threading
import aworld.trace as trace
import os
import time
from aworld.trace.instrumentation.threading import instrument_theading
from aworld.logs.util import logger, trace_logger
os.environ["MONITOR_SERVICE_NAME"] = "otlp_example"
trace.configure()
instrument_theading()
def child_thread_func():
logger.info("child thread running")
with trace.span("child_thread") as span:
trace_logger.info("child thread running")
time.sleep(1000)
def main():
logger.info("main running")
with trace.span("test_fastapi") as span:
trace_logger.info("start run child_thread_func")
threading.Thread(target=child_thread_func).start()
threading.Thread(target=child_thread_func).start()
@@ -0,0 +1,52 @@
import random
import time
import os
os.environ["MONITOR_SERVICE_NAME"] = "otlp_example"
# os.environ["LOGFIRE_WRITE_TOKEN"] = ""
os.environ["ANT_OTEL_ENDPOINT"] = "https://antcollector.alipay.com/namespace/aworld/task/aworld/otlp/api/v1/metrics"
os.environ["METRICS_SYSTEM_ENABLED"] = "true"
from aworld.metrics.metric import MetricType
from aworld.metrics.context_manager import MetricContext, ApiMetricTracker
from aworld.metrics.template import MetricTemplate
MetricContext.configure(provider="otlp",
backend="antmonitor"
)
my_counter = MetricTemplate(
type=MetricType.COUNTER,
name="my_counter",
description="My custom counter",
unit="1"
)
my_gauge = MetricTemplate(
type=MetricType.GAUGE,
name="my_gauge"
)
my_histogram = MetricTemplate(
type=MetricType.HISTOGRAM,
name="my_histogram",
buckets=[2,4,6,8,10]
)
@ApiMetricTracker()
def api():
time.sleep(random.uniform(0, 1))
def custom_code():
with ApiMetricTracker("test_custom_code"):
time.sleep(random.uniform(0, 1))
# if __name__ == '__main__':
# while 1:
# MetricContext.count(my_counter, 1, {"test_label": "b"})
# MetricContext.gauge_set(my_gauge, random.randint(1, 10), {"test_label": "b"})
# # MetricContext.histogram_record(my_histogram, random.randint(0, 1000))
# # api()
# # custom_code()
# time.sleep(random.random())
@@ -0,0 +1,48 @@
import random
import time
from aworld.metrics.metric import MetricType
from aworld.metrics.context_manager import MetricContext, ApiMetricTracker
from aworld.metrics.template import MetricTemplate
MetricContext.configure(
provider="prometheus",
backend="console"
)
my_counter = MetricTemplate(
type=MetricType.COUNTER,
name="my_counter",
description="My custom counter",
unit="1"
)
my_gauge = MetricTemplate(
type=MetricType.GAUGE,
name="my_gauge"
)
my_histogram = MetricTemplate(
type=MetricType.HISTOGRAM,
name="my_histogram",
buckets=[2, 4, 6, 8, 10]
)
@ApiMetricTracker()
def api():
time.sleep(random.uniform(0, 1))
def custom_code():
with ApiMetricTracker("test_custom_code"):
time.sleep(random.uniform(0, 1))
# if __name__ == '__main__':
# while 1:
# MetricContext.count(my_counter, random.randint(1, 10))
# MetricContext.gauge_set(my_gauge, random.randint(1, 10))
# MetricContext.histogram_record(my_histogram, random.randint(1, 10))
# api()
# custom_code()
# time.sleep(random.random())
@@ -0,0 +1,78 @@
import os # noqa
# os.environ["START_TRACE_SERVER"] = "false" # noqa
os.environ["MONITOR_SERVICE_NAME"] = "otlp_example" # noqa
# os.environ["OTLP_TRACES_ENDPOINT"] = "http://localhost:4318/v1/traces"
# os.environ["METRICS_SYSTEM_ENABLED"] = "true"
# os.environ["LOGFIRE_WRITE_TOKEN"] = (
# "Your logfire write token, "
# "create guide refer to "
# "https://logfire.pydantic.dev/docs/how-to-guides/create-write-tokens/"
# )
import aworld.trace as trace # noqa
from aworld.logs.util import logger, trace_logger
from aworld.trace.server import get_trace_server
from aworld.output.artifact import Artifact, ArtifactType
trace.configure(trace.ObservabilityConfig(trace_server_enabled=True))
class TestClass:
@trace.func_span(span_name="test_func_args")
def test_func(self, artifact: Artifact = None):
logger.info(f"this is a test func, artifact={artifact}")
@trace.func_span(span_name="test_func", attributes={"test_attr": "test_value"}, extract_args=["param1"], add_attr="add_attr_value")
def traced_func(param1: str = None, param2: int = None):
trace_logger.info("this is a traced func")
traced_func2(param1="func2_param1_value", param2=222)
traced_func3(param1="func3_param1_value", param2=333)
@trace.func_span(span_name="test_func_2", add_attr="add_attr_value")
def traced_func2(param1: str = None, param2: int = None):
name = 'func2'
trace_logger.info(f"this is a traced {name}")
raise Exception("this is a traced func2 exception")
@trace.func_span
def traced_func3(param1: str = None, param2: int = None):
trace_logger.info("this is a traced func3")
def main():
logger.info("this is a no trace log")
trace.auto_tracing("examples.trace.*", 0.01)
with trace.span("hello") as span:
span.set_attribute("parent_test_attr", "pppppp")
logger.info("hello aworld")
trace_logger.info("trace hello aworld")
with trace.span("child hello") as span2:
span2.set_attribute("child_test_attr", "cccccc")
logger.info("child hello aworld")
current_span = trace.get_current_span()
logger.info("trace_id=%s", current_span.get_trace_id())
try:
test_class = TestClass()
test_class.test_func(artifact=Artifact(
artifact_id="123",
artifact_type=ArtifactType.IMAGE,
content="123",
))
traced_func(param1="func1_param1_value", param2=111)
except Exception as e:
logger.error(f"exception: {e}")
# from examples.trace.autotrace_demo import TestClassB
# b = TestClassB()
# b.classb_function_1()
# b.classb_function_2()
# b.classb_function_1()
# b.classb_function_2()
if get_trace_server():
get_trace_server().join()
@@ -0,0 +1,69 @@
import os # noqa: E402
os.environ["MONITOR_SERVICE_NAME"] = "otlp_example" # noqa
os.environ["ANT_OTEL_ENDPOINT"] = "https://antcollector.alipay.com/namespace/aworld/task/aworld/otlp/api/v1/metrics" # noqa
os.environ["OTLP_TRACES_ENDPOINT"] = "https://antcollector.alipay.com/namespace/aworld/task/aworld_trace/otlp/api/v1/traces" # noqa
from aworld.trace.config import ObservabilityConfig
from aworld.logs.util import logger
from aworld.trace.baggage import BaggageContext
from aworld.trace.base import get_tracer_provider
from aworld.trace.instrumentation.requests import instrument_requests
from aworld.trace.instrumentation.flask import instrument_flask
import flask
import threading
import aworld.trace as trace
trace.configure(ObservabilityConfig(
trace_provider="otlp",
trace_backends=["other_otlp"],
trace_base_url="https://antcollector.alipay.com/namespace/aworld/task/aworld_trace/otlp/api/v1/traces",
metrics_provider="otlp",
metrics_backend="antmonitor",
metrics_base_url="https://antcollector.alipay.com/namespace/aworld/task/aworld/otlp/api/v1/metrics"
))
instrument_flask()
instrument_requests()
app = flask.Flask(__name__)
@app.route('/api/test')
def test():
sofa_trace_id = BaggageContext.get_baggage_value("attributes.sofa.traceid")
sofa_rpc_id = BaggageContext.get_baggage_value("attributes.sofa.rpcid")
sofa_pen_attrs = BaggageContext.get_baggage_value(
"attributes.sofa.penattrs")
sofa_sys_pen_attrs = BaggageContext.get_baggage_value(
"attributes.sofa.syspenattrs")
logger.info(
f"test sofa_trace_id={sofa_trace_id}, sofa_rpc_id={sofa_rpc_id}, sofa_pen_attrs={sofa_pen_attrs}, sofa_sys_pen_attrs={sofa_sys_pen_attrs}"
)
return 'Hello, World!'
def invoke_api():
import requests
session = requests.session()
session.headers.update({
"SOFA-TraceId": "12345678901234567890123456789012",
"SOFA-RpcId": "0.1.1",
"sofaPenAttrs": "key1=value1&key2=value2",
"sysPenAttrs": "key1=value1&key2=value2"
})
response = session.get('http://localhost:7070/api/test')
logger.info(f"invoke_api response={response.text}")
def main():
logger.info("main running")
invoke_api()
# if __name__ == "__main__":
# thread = threading.Thread(target=lambda: app.run(port=7070), daemon=True)
# thread.start()
# main()
# get_tracer_provider().force_flush(1000)
# thread.join()
@@ -0,0 +1,29 @@
import os
import json
from aworld.logs.util import logger, trace_logger
from typing import Sequence
import aworld.trace as trace
from aworld.trace.base import Span
from aworld.trace.span_cosumer import register_span_consumer, SpanConsumer
from aworld.logs.util import logger, trace_logger
os.environ["MONITOR_SERVICE_NAME"] = "otlp_example"
@register_span_consumer({"test_param": "MockSpanConsumer111"})
class MockSpanConsumer(SpanConsumer):
def __init__(self, test_param=None):
self._test_param = test_param
def consume(self, spans: Sequence[Span]) -> None:
for span in spans:
logger.info(
f"_test_param={self._test_param}, trace_id={span.get_trace_id()}, span_id={span.get_span_id()}, attributes={span.attributes}")
def main():
with trace.span("hello") as span:
span.set_attribute("parent_test_attr", "pppppp")
logger.info("hello aworld")
trace_logger.info("trace hello aworld")
@@ -0,0 +1,252 @@
import traceback
from aworld.agents.llm_agent import Agent
from aworld.config.conf import AgentConfig, ConfigDict
from aworld.core.common import Observation, ActionModel
from typing import Dict, Any, List, Union
from aworld.core.tool.base import ToolFactory
from aworld.models.llm import call_llm_model, acall_llm_model
from aworld.trace.config import ObservabilityConfig
from aworld.utils.common import sync_exec
from aworld.logs.util import logger
from aworld.core.agent.swarm import Swarm
from aworld.runner import Runners
from aworld.trace.server import get_trace_server
from aworld.runners.state_manager import RuntimeStateManager, RunNode
import aworld.trace as trace
trace.configure(ObservabilityConfig(trace_server_enabled=True,
metrics_provider="otlp",
metrics_backend="antmonitor",
metrics_base_url="https://antcollector.alipay.com/namespace/aworld/task/aworld/otlp/api/v1/metrics"))
class TraceAgent(Agent):
def __init__(self,
conf: Union[Dict[str, Any], ConfigDict, AgentConfig],
name: str,
**kwargs):
super().__init__(conf, name, **kwargs)
def policy(self, observation: Observation, info: Dict[str, Any] = {}, **kwargs) -> List[ActionModel]:
"""use trace tool to get trace data, and call llm to summary
Args:
observation: The state observed from tools in the environment.
info: Extended information is used to assist the agent to decide a policy.
Returns:
ActionModel sequence from agent policy
"""
self._finished = False
self.desc_transform()
tool_name = "trace"
tool = ToolFactory(tool_name, asyn=False)
tool.reset()
tool_params = {}
action = ActionModel(tool_name=tool_name,
action_name="get_trace",
agent_name=self.id(),
params=tool_params)
message = tool.step(action)
observation, _, _, _, _ = message.payload
llm_response = None
messages = self.messages_transform(content=observation.content,
sys_prompt=self.system_prompt,
agent_prompt=self.agent_prompt)
try:
llm_response = call_llm_model(
self.llm,
messages=messages,
model=self.model_name,
temperature=self.conf.llm_config.llm_temperature
)
logger.info(f"Execute response: {llm_response.message}")
except Exception as e:
logger.warn(traceback.format_exc())
raise e
finally:
if llm_response:
if llm_response.error:
logger.info(
f"{self.id()} llm result error: {llm_response.error}")
else:
logger.error(f"{self.id()} failed to get LLM response")
raise RuntimeError(
f"{self.id()} failed to get LLM response")
agent_result = sync_exec(self.model_output_parser.parse, llm_response, agent_id=self.id())
if not agent_result.is_call_tool:
self._finished = True
return agent_result.actions
async def async_policy(self, observation: Observation, info: Dict[str, Any] = {}, **kwargs) -> List[ActionModel]:
self._finished = False
self.desc_transform()
tool_name = "trace"
tool = ToolFactory(tool_name, asyn=False)
tool.reset()
tool_params = {}
action = ActionModel(tool_name=tool_name,
action_name='get_trace',
agent_name=self.id(),
params=tool_params)
message = tool.step([action])
observation, _, _, _, _ = message.payload
llm_response = None
messages = self.messages_transform(content=observation.content,
sys_prompt=self.system_prompt,
agent_prompt=self.agent_prompt)
try:
llm_response = await acall_llm_model(
self.llm,
messages=messages,
model=self.model_name,
temperature=self.conf.llm_config.llm_temperature
)
logger.info(f"Execute response: {llm_response.message}")
except Exception as e:
logger.warn(traceback.format_exc())
raise e
finally:
if llm_response:
if llm_response.error:
logger.info(
f"{self.id()} llm result error: {llm_response.error}")
else:
logger.error(f"{self.id()} failed to get LLM response")
raise RuntimeError(
f"{self.id()} failed to get LLM response")
agent_result = await self.model_output_parser.parse(llm_response, agent_id=self.id())
if not agent_result.is_call_tool:
self._finished = True
return agent_result.actions
search_sys_prompt = "You are a helpful search agent."
search_prompt = """
Please act as a search agent, constructing appropriate keywords and searach terms, using search toolkit to collect relevant information, including urls, webpage snapshots, etc.
Here are the question: {task}
pleas only use one action complete this task, at least results 6 pages.
"""
summary_sys_prompt = "You are a helpful general summary agent."
summary_prompt = """
Summarize the following text in one clear and concise paragraph, capturing the key ideas without missing critical points.
Ensure the summary is easy to understand and avoids excessive detail.
Here are the content:
{task}
"""
trace_sys_prompt = "You are a helpful trace summary agent."
trace_prompt = """
Please act as a trace summary agent, Using the provided trace data, summarize the main tasks completed by each agent and their token usage,
whether the run_type attribute of span is an agent or a large model call:
run_type=AGNET and is_event=True represents the agent,
run_type=LLM and is_event=False represents the large model call.
run_type=TOOL and is_event=True represents the tool call.
The tool call and large model call of agent are manifested as the nearest child span of AGENT Span.
Please output in the following standard JSON format without any additional explanatory text:
[{{"agent":"xxx","summary":"xxx","token_usage":"xxx","input_tokens":"xxx","output_tokens":"xxx","use_tools":["xxx"]}}]
Here are the trace data: {task}
"""
def build_run_flow(nodes: List[RunNode]):
graph = {}
start_nodes = []
for node in nodes:
if hasattr(node, 'parent_node_id') and node.parent_node_id:
if node.parent_node_id not in graph:
graph[node.parent_node_id] = []
graph[node.parent_node_id].append(node.node_id)
else:
start_nodes.append(node.node_id)
for start in start_nodes:
print("-----------------------------------")
_print_tree(graph, start, "", True)
print("-----------------------------------")
def _print_tree(graph, node_id, prefix, is_last):
print(prefix + ("└── " if is_last else "├── ") + node_id)
if node_id in graph:
children = graph[node_id]
for i, child in enumerate(children):
_print_tree(graph, child, prefix +
(" " if is_last else ""), i == len(children) - 1)
def run():
agent_config = AgentConfig(
llm_provider="openai",
llm_model_name="DeepSeek-V3-Function-Call",
llm_temperature=0.3,
llm_base_url="http://localhost:34567",
llm_api_key="dummy-key",
)
search = Agent(
conf=agent_config,
name="search_agent",
system_prompt=search_sys_prompt,
agent_prompt=search_prompt,
tool_names=["search_api"]
)
summary = Agent(
conf=agent_config,
name="summary_agent",
system_prompt=summary_sys_prompt,
agent_prompt=summary_prompt
)
trace = TraceAgent(
conf=agent_config,
name="trace_agent",
system_prompt=trace_sys_prompt,
agent_prompt=trace_prompt
)
# default is sequence swarm mode
swarm = Swarm(search, summary, trace, max_steps=1, event_driven=True)
prefix = "search baidu:"
# can special search google, wiki, duck go, or baidu. such as:
# prefix = "search wiki: "
try:
res = Runners.sync_run(
input=prefix + """What is an agent.""",
swarm=swarm,
session_id="123"
)
print(res.answer)
except Exception as e:
logger.error(traceback.format_exc())
state_manager = RuntimeStateManager.instance()
nodes = state_manager.get_nodes("123")
logger.info(f"session 123 nodes: {nodes}")
build_run_flow(nodes)
get_trace_server().join()