Skip to content
Open
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
34 changes: 34 additions & 0 deletions examples/templates/sales_call_news_researcher/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Sales Call News Researcher — Briefing emails for sales calls based on company news."""

from .agent import (
SalesCallNewsResearcher,
conversation_mode,
default_agent,
edges,
entry_node,
entry_points,
goal,
identity_prompt,
loop_config,
nodes,
pause_nodes,
terminal_nodes,
)
from .config import default_config, metadata

__all__ = [
"SalesCallNewsResearcher",
"default_agent",
"goal",
"nodes",
"edges",
"entry_node",
"entry_points",
"pause_nodes",
"terminal_nodes",
"conversation_mode",
"identity_prompt",
"loop_config",
"default_config",
"metadata",
]
122 changes: 122 additions & 0 deletions examples/templates/sales_call_news_researcher/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
"""CLI entry point for Sales Call News Researcher."""

import asyncio
import json
import logging
import sys

import click

from .agent import SalesCallNewsResearcher, default_agent


def setup_logging(verbose=False, debug=False):
if debug:
level, fmt = logging.DEBUG, "%(asctime)s %(name)s: %(message)s"
elif verbose:
level, fmt = logging.INFO, "%(message)s"
else:
level, fmt = logging.WARNING, "%(levelname)s: %(message)s"
logging.basicConfig(level=level, format=fmt, stream=sys.stderr)


@click.group()
@click.version_option(version="1.0.0")
def cli():
"""Sales Call News Researcher — Prepare company news briefings before sales calls."""
pass


@cli.command()
@click.option("--verbose", "-v", is_flag=True)
def run(verbose):
"""Execute the news researcher workflow."""
setup_logging(verbose=verbose)
result = asyncio.run(default_agent.run({}))
click.echo(
json.dumps(
{"success": result.success, "output": result.output}, indent=2, default=str
)
)
sys.exit(0 if result.success else 1)


@cli.command()
def tui():
"""Launch TUI dashboard."""
from pathlib import Path

from framework.llm import LiteLLMProvider
from framework.runner.tool_registry import ToolRegistry
from framework.runtime.agent_runtime import create_agent_runtime
from framework.runtime.execution_stream import EntryPointSpec
from framework.tui.app import AdenTUI

async def run_tui():
agent = SalesCallNewsResearcher()
agent._tool_registry = ToolRegistry()
storage = Path.home() / ".hive" / "agents" / "sales_call_news_researcher"
storage.mkdir(parents=True, exist_ok=True)
mcp_cfg = Path(__file__).parent / "mcp_servers.json"
if mcp_cfg.exists():
agent._tool_registry.load_mcp_config(mcp_cfg)
llm = LiteLLMProvider(
model=agent.config.model,
api_key=agent.config.api_key,
api_base=agent.config.api_base,
)
runtime = create_agent_runtime(
graph=agent._build_graph(),
goal=agent.goal,
storage_path=storage,
entry_points=[
EntryPointSpec(
id="start",
name="Start",
entry_node="calendar-scan",
trigger_type="manual",
isolation_level="isolated",
)
],
llm=llm,
tools=list(agent._tool_registry.get_tools().values()),
tool_executor=agent._tool_registry.get_executor(),
)
await runtime.start()
try:
app = AdenTUI(runtime)
await app.run_async()
finally:
await runtime.stop()

asyncio.run(run_tui())


@cli.command()
def info():
"""Show agent info."""
data = default_agent.info()
click.echo(
f"Agent: {data['name']}\nVersion: {data['version']}\nDescription: {data['description']}"
)
click.echo(
f"Nodes: {', '.join(data['nodes'])}\n"
f"Client-facing: {', '.join(data['client_facing_nodes'])}"
)


@cli.command()
def validate():
"""Validate agent structure."""
v = default_agent.validate()
if v["valid"]:
click.echo("Agent is valid")
else:
click.echo("Errors:")
for e in v["errors"]:
click.echo(f" {e}")
sys.exit(0 if v["valid"] else 1)


if __name__ == "__main__":
cli()
Loading
Loading