Quick Start

Getting Started

Yoker provides an interactive chat interface with Ollama and tool calling capabilities.

Architecture: Yoker uses an event-driven, library-first design. The Agent emits events (thinking chunks, content, tool calls) that handlers subscribe to. This makes the library usable in headless, web, and GUI contexts.

Architecture Diagram

Prerequisites

  • Python 3.10 or higher

  • Ollama running with at least one model

Install

pip install -e .

Or from PyPI:

pip install yoker

Run

python -m yoker

Or with a configuration file:

python -m yoker --config yoker.toml

Library Usage (Headless)

import asyncio
from yoker import Agent
from yoker.events import Event, ContentChunkEvent

# Create a custom async event handler (recommended)
class MyAsyncHandler:
    """Async event handler for processing events.

    Async handlers are recommended for most use cases, especially when
    performing I/O operations like writing to files, making network calls,
    or interacting with databases.
    """
    async def __call__(self, event: Event) -> None:
        if isinstance(event, ContentChunkEvent):
            print(event.text, end='', flush=True)

# Sync handlers are also supported for simple, fast operations
class MySyncHandler:
    """Sync handler for simple operations (no I/O).

    Sync handlers are supported for cases where the handler just
    performs fast, non-blocking operations like logging or counters.
    """
    def __call__(self, event: Event) -> None:
        if isinstance(event, ContentChunkEvent):
            print(event.text, end='', flush=True)

async def main():
    # Create agent and attach async handler
    agent = Agent(model="llama3.2")
    agent.add_event_handler(MyAsyncHandler())

    # Use the agent programmatically (all methods are async)
    await agent.begin_session()
    await agent.process("What is 2+2?")
    await agent.end_session()

# Run the async main function
asyncio.run(main())

Async Model

Yoker is built with an async-first architecture:

  • All Agent methods are async: begin_session(), process(), and end_session() are all coroutines

  • Event handlers can be async: Handlers receive events in the same asyncio task as process()

  • No thread pool bridging needed: Async handlers can directly await I/O operations

class DatabaseHandler:
    """Example async handler writing to a database."""
    
    def __init__(self, db_connection):
        self.db = db_connection
    
    async def __call__(self, event: Event) -> None:
        if isinstance(event, ContentEndEvent):
            # Direct await - no run_coroutine_threadsafe needed!
            await self.db.save_response(event.total_length)

async def main():
    agent = Agent(model="llama3.2")
    agent.add_event_handler(DatabaseHandler(db))
    
    await agent.begin_session()
    await agent.process("Hello")  # Handler runs in same event loop
    await agent.end_session()

Threading Model:

Context

Where handlers run

await agent.process()

Same asyncio task

Interactive CLI

Main asyncio event loop

Web server (FastAPI)

Request handler’s event loop

Handlers run synchronously within the asyncio event loop. For long-running operations, use async handlers that yield control (e.g., await asyncio.sleep(0)) or offload to a separate executor.

Interactive Session

Yoker v0.3.0 - Using model: glm-5:cloud
Thinking mode: enabled (use /think on|off to toggle)
Type /help for available commands.
Press Ctrl+D (or Ctrl+Z on Windows) to quit.

> /help

Available commands:

  /help - Show available commands
  /think - Enable/disable thinking mode: /think [on|off]

Type a message without / prefix to chat with the LLM.

> What's in the README.md file?

I'll read the README.md file for you.

The README.md file describes **Yoker**, a Python-based agent harness...

> ^D
Goodbye!

Interactive Input Features

The session supports:

Feature

How to use

Multiline input

Esc+Enter adds newlines, Enter submits

Command history

Up/Down arrows navigate previous messages

History search

Ctrl+R searches through history

Mouse support

Click to position cursor

Slash Commands

Command

Description

/help

Show available commands

/think on|off

Enable/disable LLM thinking trace

Thinking Mode

When enabled, the LLM shows its reasoning process in gray:

[Thinking]
Let me analyze this request...
I should check the file structure first...

[Response]
Based on my analysis, here's what I found...

Command Line Options

python -m yoker --help

Options:
  -c, --config PATH    Path to configuration file (default: yoker.toml)
  -m, --model MODEL    Model to use (overrides config)
  -a, --agent PATH     Path to agent definition file (Markdown with frontmatter)

Session Persistence

Yoker supports session persistence for resuming conversations:

# Start a session with persistence
python -m yoker --persist

# Resume a previous session
python -m yoker --resume <session_id>

When using --persist, the session is saved after each turn. Use --resume to continue a previous session with full context restored.

Programmatic usage:

import asyncio
from pathlib import Path
from yoker.agent import Agent
from yoker.context import BasicPersistenceContextManager

async def main():
    # Create context manager for persistence
    context = BasicPersistenceContextManager(
      storage_path=Path(".yoker/sessions"),
      session_id="my-session"
    )

    # Create agent with context
    agent = Agent(context_manager=context)

    # Use the agent (all methods are async)
    await agent.begin_session()
    await agent.process("What is 2+2?")
    await agent.end_session()

    # Later, resume the session
    context = BasicPersistenceContextManager(
      storage_path=Path(".yoker/sessions"),
      session_id="my-session"
    )
    agent = Agent(context_manager=context)
    # Context is automatically loaded

asyncio.run(main())

Tools

Yoker provides several tools for file operations and subagent spawning:

Tool

Description

read

Read file contents with guardrails

list

Directory listing with pattern filtering

write

Write files with overwrite protection

update

Edit existing files with replace/insert/delete

search

Search file contents or filenames

existence

Check if files or folders exist

mkdir

Create directories with parent creation

git

Git operations with permission-controlled commit/push

agent

Spawn subagents with isolated context

Agent Tool

The agent tool allows spawning subagents for specialized tasks:

Agent Tool Demo
> Use the agent tool to spawn a researcher agent to find all TODO comments

[Tool Call] agent(agent_path="examples/agents/researcher.md", prompt="Find all TODO comments")

The researcher agent found 15 TODO items across the codebase...

Key features:

  • Isolated context: Subagents start with fresh context

  • Recursion limits: Maximum depth of 3 by default

  • Timeout: 5-minute default execution limit

  • Tool filtering: Subagents use only their defined tools

Agent Definitions

Yoker supports loading agent definitions from Markdown files with YAML frontmatter. This allows you to define custom system prompts and tool availability.

Agent Definition Format

Create a file like examples/agents/researcher.md:

---
name: researcher
description: Research assistant that searches and reads files
tools: List, Read, Search
color: blue
---

# Researcher Agent

You are a research assistant specialized in finding and analyzing information.

## Workflow

1. Use Search to find relevant files
2. Use Read to examine file contents
3. Compile findings into a structured report

Using Agent Definitions

# Load an agent definition
python -m yoker --agent examples/agents/researcher.md

Programmatically:

from yoker.agent import Agent
from yoker.agents import load_agent_definition, validate_agent_definition
from yoker.config import load_config

# Load configuration and agent
config = load_config("yoker.toml")
agent_def = load_agent_definition("agents/researcher.md")

# Validate agent tools against config
warnings = validate_agent_definition(agent_def, config.tools)

# Create agent with definition
agent = Agent(config=config, agent_definition=agent_def)
# agent.messages[0] now contains the system prompt from the Markdown body

Example Agents

Agent

File

Description

Main

examples/agents/main.md

Default assistant with read-only tools

Researcher

examples/agents/researcher.md

Research assistant with search capabilities

Markdown

examples/agents/markdown.md

Formats all responses as structured Markdown

Configuration

Configuration File

Create a yoker.toml file in your project directory:

[harness]
name = "my-yoke"
log_level = "INFO"

[backend]
provider = "ollama"

[backend.ollama]
base_url = "http://localhost:11434"
model = "llama3.2:latest"
timeout_seconds = 60

[backend.ollama.parameters]
temperature = 0.7
top_p = 0.9

[tools.read]
enabled = true
allowed_extensions = [".txt", ".md", ".py", ".json"]

[logging]
format = "json"
include_tool_calls = true

See examples/yoker.toml for the full configuration reference.

Environment Variables

Yoker auto-discovers configuration files in this order:

  1. ./yoker.toml (current directory)

  2. ~/.yoker.toml (user home directory)

  3. Built-in defaults

You can also specify an explicit config file:

python -m yoker --config path/to/config.toml

Available Tools

Tool

Purpose

read

Read file contents

list

List directory contents with pattern filtering

write

Write content to files with overwrite protection

update

Edit existing files with replace, insert, and delete

search

Search file contents with regex or filenames with glob

git

Git operations (status, log, diff, branch, show)

Tool Examples

Read Tool

Read Tool Demo

Reading the first 3 lines of README.md.

List Tool

List Tool Demo

Listing files matching CLAUDE* in the current directory.

Write Tool

Write Tool Demo

Writing “Hello from Yoker!” to /tmp/yoker-demo.txt and reading it back.

Update Tool

Update Tool Demo

Replacing text in an existing file with the update tool.

Search Tool

Search Tool Demo

Searching for content with regex patterns or filenames with glob patterns.

Git Tool

Git Tool Demo

Running Git operations (status, log, diff) on a repository.

Commands

Commands Demo

Using /help, /think on, and /think off slash commands.

Thinking Mode

Thinking Mode Demo

Thinking mode enabled shows the LLM reasoning process in gray before the response.


Next Steps