Skip to main content

A minimal Python SDK for agent loops, with streaming events, clean tool contracts, and zero ceremony.

Project description

EasyHarness

A minimal Python SDK for agent loops, with streaming events, clean tool contracts, and zero ceremony.

Python 3.10+ FileGlide Strands Agents LiteLLM

Small public surface. Strong defaults. Explicit control.

Why EasyHarness

EasyHarness is designed for local agent workflows where a tiny SDK surface matters more than a large framework.

It works well for coding agents, but it is not limited to them. Any agent that benefits from strict tool contracts, streaming events, and explicit runtime control can use the same SDK surface.

It gives you:

  • A single primary runtime entry point through Agent
  • Strict tool metadata and output contracts through tool and ToolOutput
  • A unified streaming event model for thinking, tool, assistant, compression, and system events
  • An official FileGlide-backed filesystem toolset that can be auto-loaded by default or scoped explicitly

Public Surface

The root package intentionally exposes only five public names:

  • Agent
  • ModelConfig
  • AgentEvent
  • ToolOutput
  • tool

Everything else stays behind internal modules or the explicit easyharness.toolset package.

Typical Usage

1. Define a tool and run an agent

from easyharness import Agent, ModelConfig, ToolOutput, tool


@tool(
    name="ping_tool",
    purpose="Return a fixed response for a minimal tool-flow check.",
    when_to_use=(
        "Use this when the model needs a trivial tool call to verify that the "
        "tool pipeline is available."
    ),
    parameters={},
    returns="A fixed pong response.",
    common_failures=["This tool does not fail under normal conditions."],
)
def ping_tool() -> ToolOutput:
    return ToolOutput(
        data={"value": "pong"},
        model_text="pong",
        preview="pong",
        detail='{"value": "pong"}',
    )


agent = Agent(
    model=ModelConfig(
        model="openai/gpt-4.1-mini",
        api_key="YOUR_API_KEY",
    ),
    system_prompt="You are a precise agent.",
    tools=[ping_tool],
)

print(agent.run("Call the ping tool and confirm that the tool pipeline works."))

2. Use the default FileGlide integration

Agent can auto-load the official FileGlide-backed toolset, so the shortest agent setup does not need a manual tools=[...] list.

from easyharness import Agent, ModelConfig


agent = Agent(
    model=ModelConfig(
        model="openai/gpt-4.1-mini",
        api_key="YOUR_API_KEY",
    ),
    system_prompt="You are a careful agent.",
)

print(
    agent.run(
        "List the workspace, read pyproject.toml, and summarize the SDK shape."
    )
)
Official default FileGlide tools
  • fileglide_list_tree
  • fileglide_search_paths
  • fileglide_read_text
  • fileglide_search_text
  • fileglide_edit_text
  • fileglide_manage_paths
  • fileglide_inspect_path

3. Disable the default FileGlide tools

If you want a stricter default runtime with no filesystem tool auto-loading, disable it explicitly.

from easyharness import Agent, ModelConfig


agent = Agent(
    model=ModelConfig(
        model="openai/gpt-4.1-mini",
        api_key="YOUR_API_KEY",
    ),
    system_prompt="You are a careful agent.",
    enable_fileglide=False,
)

4. Build a scoped official FileGlide toolset

When you need explicit control over the filesystem scope, disable the default auto-load and pass a scoped official toolset from easyharness.toolset.

from easyharness import Agent, ModelConfig
from easyharness.toolset import build_fileglide_tools


agent = Agent(
    model=ModelConfig(
        model="openai/gpt-4.1-mini",
        api_key="YOUR_API_KEY",
    ),
    system_prompt="You are a careful agent.",
    enable_fileglide=False,
    tools=build_fileglide_tools(default_root="D:/Projects/PythonProjects/EasyHarness"),
)

build_fileglide_tools(default_root=...) creates the official scoped toolset. Paths that escape the configured root are rejected by FileGlide scope protection.

Each official fileglide_* tool also accepts an optional root argument for that single call. When provided, it overrides the builder's default root without additional SDK-level path-range restrictions.

tools = build_fileglide_tools(default_root="D:/Projects/PythonProjects/EasyHarness")
tool_map = {tool.tool_name: tool for tool in tools}

result = tool_map["fileglide_read_text"](
    target="EasyHarness/pyproject.toml",
    root="D:/Projects/PythonProjects",
)

Event Stream

agent.stream(prompt) yields a unified AgentEvent stream. The public event kinds are:

  • thinking
  • tool
  • assistant
  • compress
  • system

Each event uses the same status vocabulary:

  • started
  • delta
  • completed
  • failed
for event in agent.stream("Inspect the workspace and explain the next step."):
    print(event.kind, event.status, event.text)

Design Boundaries

EasyHarness is intentionally small. v1 does not try to solve:

  • UI components
  • Environment-variable orchestration layers
  • Plugin platforms
  • Multi-agent orchestration
  • Root-package re-export sprawl for toolset builders

Summary

EasyHarness is most useful when you want:

  • A minimal Agent API
  • Strict tool definitions
  • Streaming runtime visibility
  • A practical, official FileGlide-backed filesystem toolset

If that is your shape of problem, the shortest path is:

  1. Create an Agent
  2. Define tools with @tool(...)
  3. Use the default FileGlide integration or pass a scoped official toolset

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

easyharness-0.1.0.tar.gz (30.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

easyharness-0.1.0-py3-none-any.whl (25.3 kB view details)

Uploaded Python 3

File details

Details for the file easyharness-0.1.0.tar.gz.

File metadata

  • Download URL: easyharness-0.1.0.tar.gz
  • Upload date:
  • Size: 30.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for easyharness-0.1.0.tar.gz
Algorithm Hash digest
SHA256 8da5d898d042969480285d235ccfa2db528aca0fac86f5970c8d7cb06c2ccad2
MD5 2d47c3df202dd4c9275eebe60e1a1674
BLAKE2b-256 b57edf10366b8fb9e65e754f429b768c832870b22bbe44ec4c5966f0d679cd50

See more details on using hashes here.

File details

Details for the file easyharness-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: easyharness-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 25.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for easyharness-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bdfd35f3f949a5a0ab57950534d963bad84627ce662f833ec44aa9a20df54efb
MD5 e30606fabb8a257a34ddcc6bc348af2c
BLAKE2b-256 5cb921558d43c03870466de51757fa87b4f639eb713394cd248a09d4b8e4e547

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page