diff --git a/dify-agent/examples/agenton_basics.py b/dify-agent/examples/agenton/basics.py similarity index 99% rename from dify-agent/examples/agenton_basics.py rename to dify-agent/examples/agenton/basics.py index 981c789e5c..3f32b9c432 100644 --- a/dify-agent/examples/agenton_basics.py +++ b/dify-agent/examples/agenton/basics.py @@ -1,4 +1,4 @@ -"""Run with: uv run --project dify-agent python examples/agenton_basics.py.""" +"""Run with: uv run --project dify-agent python examples/agenton/basics.py.""" from __future__ import annotations diff --git a/dify-agent/examples/agenton_pydantic_ai.py b/dify-agent/examples/agenton/pydantic_ai_bridge.py similarity index 79% rename from dify-agent/examples/agenton_pydantic_ai.py rename to dify-agent/examples/agenton/pydantic_ai_bridge.py index c5fdfffe3c..1c679ab95a 100644 --- a/dify-agent/examples/agenton_pydantic_ai.py +++ b/dify-agent/examples/agenton/pydantic_ai_bridge.py @@ -1,12 +1,13 @@ -"""Run with: uv run --project dify-agent python examples/agenton_pydantic_ai.py.""" +"""Run with: uv run --project dify-agent python examples/agenton/pydantic_ai_bridge.py.""" from __future__ import annotations +import asyncio +import json from dataclasses import dataclass -from typing import cast -from pydantic_ai import Agent, RunContext, Tool -from pydantic_ai.messages import ToolCallPart, BuiltinToolCallPart +from pydantic_ai import Agent, RunContext +from pydantic_ai.messages import BuiltinToolCallPart, ModelMessage, ToolCallPart from pydantic_ai.models.test import TestModel from agenton.compositor import Compositor, CompositorLayerConfig @@ -16,7 +17,6 @@ from agenton_collections.layers.pydantic_ai import PydanticAIBridgeLayer from agenton_collections.transformers import PYDANTIC_AI_TRANSFORMERS -import json @dataclass(frozen=True, slots=True) class AgentProfile: name: str @@ -49,8 +49,8 @@ async def main() -> None: tone="precise and friendly", ) pydantic_ai_bridge = PydanticAIBridgeLayer[AgentProfile]( - prefix=(profile_prompt, tone_prompt), - tool_entries=(Tool(write_tagline),), + prefix=("Prefer concrete details.", profile_prompt, tone_prompt), + tool_entries=(write_tagline,), ) compositor = Compositor[ @@ -96,18 +96,28 @@ async def main() -> None: tools=compositor.tools, ) for prompt in compositor.prompts: - agent.system_prompt(prompt) + _ = agent.system_prompt(prompt) result = await agent.run( "Use the tools for 'layer composition'.", deps=pydantic_ai_bridge.run_deps, ) - for message in result.all_messages(): + for line in _format_messages(result.all_messages()): + print(line) + + +def _format_messages(messages: list[ModelMessage]) -> list[str]: + lines: list[str] = [] + for message in messages: for part in message.parts: - print(f"{type(part).__name__}: {part.content if not isinstance(part, (ToolCallPart, BuiltinToolCallPart)) else part.tool_name + '(' + json.dumps(part.args, ensure_ascii=False) + ')'}") + if isinstance(part, ToolCallPart | BuiltinToolCallPart): + args = json.dumps(part.args, ensure_ascii=False) + lines.append(f"{type(part).__name__}: {part.tool_name}({args})") + else: + lines.append(f"{type(part).__name__}: {part.content}") + return lines if __name__ == "__main__": - import asyncio asyncio.run(main()) diff --git a/dify-agent/tests/local/examples/test_agenton_examples.py b/dify-agent/tests/local/examples/test_agenton_examples.py new file mode 100644 index 0000000000..b154eb0491 --- /dev/null +++ b/dify-agent/tests/local/examples/test_agenton_examples.py @@ -0,0 +1,35 @@ +import subprocess +import sys +from pathlib import Path + + +PROJECT_ROOT = Path(__file__).resolve().parents[3] + + +def _run_example(path: str) -> subprocess.CompletedProcess[str]: + return subprocess.run( + [sys.executable, path], + cwd=PROJECT_ROOT, + text=True, + capture_output=True, + check=False, + ) + + +def test_agenton_basics_example_smoke() -> None: + result = _run_example("examples/agenton/basics.py") + + assert result.returncode == 0, result.stderr + assert "Prompts:" in result.stdout + assert "Tools:" in result.stdout + assert "Lifecycle: ['create', 'tmp_leave', 'reenter', 'delete']" in result.stdout + + +def test_agenton_pydantic_ai_example_smoke() -> None: + result = _run_example("examples/agenton/pydantic_ai_bridge.py") + + assert result.returncode == 0, result.stderr + assert "SystemPromptPart: Prefer concrete details." in result.stdout + assert "ToolCallPart: count_words(" in result.stdout + assert "ToolCallPart: write_tagline(" in result.stdout + assert "TextPart:" in result.stdout