Skip to content

Agent

LLMling-agent provides an agent implementation based on pydantic-ai that integrates with the LLMling resource and tool system. The agent can be used standalone or as part of a larger application.

Basic Usage

config.yml

tools:
  open_browser:
    import_path: "webbrowser.open"
  analyze:
    import_path: "module.some_tool_for_analysis"

resources:
  llmling_agent_manual:
    type: path
    path: "https://raw.githubusercontent.com/phil65/llmling_agent/refs/heads/main/README.md"
    description: "LLMling Agent Manual"

Create and use an agent:

from llmling import RuntimeConfig
from llmling_agent import Agent
from pydantic import BaseModel


async with RuntimeConfig.open("config.yml") as runtime:
    # Create agent with string output. It will have all resources and tools available from the config.
    basic_agent = Agent(
        runtime,
        model="openai:gpt-4",
        system_prompt="You are a helpful assistant."
    )
    await basic_agent.run("Open google for me.")  # Uses tool to open browser
    # Create agent with structured output


    # Define return type
    class Analysis(BaseModel):
        summary: str
        suggestions: list[str]


    typed_agent = Agent[Any, Analysis](
        runtime,
        result_type=Analysis,
        model="openai:gpt-4",
        system_prompt=[
            "You are a code analysis assistant.",
            "Always provide structured results.",
        ]
    )
    result = await typed_agent.run("Analyze this code.")
    print(result.data.summary)         # Typed access
    print(result.data.suggestions)     # Type-checked

Agent Configuration

The agent can be configured with various options:

agent = Agent(
    runtime,
    # Model settings
    model="openai:gpt-4",            # Model to use
    result_type=Analysis,            # Optional result type

    # Prompt configuration
    system_prompt=[                  # Static system prompts
        "You are an assistant.",
        "Be concise and clear.",
    ],
    name="code-assistant",          # Agent name

    # Execution settings
    retries=3,                      # Max retries
)

Running the Agent

Different ways to run the agent:

# Basic run
result = await agent.run("Analyze this code.")

# With message history
from pydantic_ai import messages

history = [
    messages.Message(role="user", content="Previous message"),
    messages.Message(role="assistant", content="Previous response")
]
result = await agent.run("Follow up question", message_history=history)

# Stream responses
async with agent.run_stream("Analyze this.") as stream:
    async for message in stream:
        print(message.content)

# Synchronous operation (convenience wrapper)
result = agent.run_sync("Quick question")

Customizing Agent Behavior

Add custom tools and system prompts:

class CodeAgent(Agent[Any, Analysis]):
    def __init__(self, runtime: RuntimeConfig):
        super().__init__(
            runtime,
            result_type=Analysis,
            model="openai:gpt-4"
        )
        self._setup_tools()

    def _setup_tools(self):
        @self.tool
        async def analyze_code(
            ctx: RunContext[AgentContext],
            code: str
        ) -> dict[str, Any]:
            """Analyze Python code."""
            return await ctx.deps.execute_tool("analyze", code=code)

        @self.system_prompt
        async def get_language_prompt(
            ctx: RunContext[AgentContext]
        ) -> str:
            """Dynamic system prompt."""
            langs = await ctx.deps.execute_tool("list_languages")
            return f"Supported languages: {', '.join(langs)}"

Tools and System Prompts

Register tools and prompts with decorators:

# Register a tool
@agent.tool
async def my_tool(
    ctx: RunContext[AgentContext],
    arg: str
) -> str:
    """Tool description."""
    return f"Processed: {arg}"

# Register a plain tool (no context)
@agent.tool_plain
def plain_tool(text: str) -> str:
    """Plain tool without context."""
    return text.upper()

# Register dynamic system prompt
@agent.system_prompt
async def get_prompt(ctx: RunContext[AgentContext]) -> str:
    """Dynamic system prompt."""
    resources = await ctx.deps.list_resource_names()
    return f"Available resources: {', '.join(resources)}"


## Event Handling

The agent can handle runtime events:

```python
class MyAgent(Agent[Any]):
    async def handle_event(self, event: Event):
        """Handle runtime events."""
        match event.type:
            case "RESOURCE_MODIFIED":
                print(f"Resource changed: {event.name}")
            case "TOOL_ADDED":
                print(f"New tool available: {event.name}")

Best Practices

Type Safety

  • Use typed results when possible
  • Validate tool inputs/outputs
  • Handle model errors appropriately

Resource Management

# Proper cleanup with context manager
async with runtime as r:
    agent = Agent(r)
    try:
        result = await agent.run("Query")
    except Exception as e:
        print(f"Agent error: {e}")

Tool Design

  • Keep tools focused
  • Provide clear descriptions
  • Use type hints
  • Handle errors gracefully
  • Report progress for long operations

System Prompts

  • Keep them clear and focused
  • Use dynamic prompts when needed
  • Don't leak implementation details
  • Consider using templates

Next Steps

For more information about agents and integration examples, see: - Agent Examples - Tool Development - Type System