Observed since 20 Oct, 22:09 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
agent-harness-kit
A portable agent harness and supervisor orchestration loop for raw LLM backends and multi-agent frameworks.
A tiny, provider-neutral agent interoperability harness for Python: one Protocol, a JSON-serializable shared context, pluggable memory, and a supervisor shell that can coordinate mixed existing agents without making their framework your application boundary.
Why use it? It gives developers one small, provider-neutral supervisor, context, and memory contract around agents they already have—without forcing the entire application into one vendor or framework.
Release status:
0.1.0is the published release. This working tree is a documentation-only0.1.1candidate; it is not yet published.
agent-harness-kit gives independently built agents one narrow contract:
run_step(context: HarnessContext) -> StepResult
The HarnessLoop asks a supervisor which registered agent should run next, passes the same serializable HarnessContext through every step, records results through a replaceable MemoryProvider, and stops on completion or a configured step limit.
Concrete benefits
Ideal for prototypes, portfolio projects, framework migration spikes, small internal tools, and teams that already have heterogeneous agents but need a simple shared supervisor/session boundary. It is also useful as reference code for learning the supervisor pattern.
Not a replacement for full graph runtimes, durable execution, built-in tracing or evaluations, built-in guardrails, large tool ecosystems, or managed deployment platforms. If you need those capabilities, use a framework or platform that provides them and optionally place this harness around a suitable boundary. The included LangGraph, CrewAI, and Strands adapters remain integration templates whose run_step methods must be implemented for your objects.
Existing agents and model calls
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ Claude/API │ │ OpenAI/API │ │ LangGraph* │ │ CrewAI* … │
└─────┬──────┘ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘
└────────────── adapters / wrappers ──────────────┘
│
AgentBackend Protocol
run_step(HarnessContext) -> StepResult
│
┌─────────▼─────────┐
│ HarnessLoop │
│ supervisor routes│
└───────┬───────────┘
│ read / merge / save
┌───────▼───────────┐
│ HarnessContext │
│ JSON-serializable │
└───────┬───────────┘
│
┌─────────────▼─────────────┐
│ MemoryProvider Protocol │
│ in-memory · SQLite · yours│
└───────────────────────────┘
* LangGraph, CrewAI, and Strands adapters are templates in v0.1.x.
Framework-specific code stays in agent_harness_kit/backends/. The core package uses only the Python standard library. Top-level imports remain safe because backend SDK imports are deferred until backend construction.
This is a scope comparison, not a claim that the projects are interchangeable.
| Project | What official documentation emphasizes | Where agent-harness-kit differs |
|---|---|---|
| agent-harness-kit | A tiny AgentBackend protocol, serializable context, pluggable memory, and a supervisor loop. Zero third-party core runtime dependencies; provider-neutral; designed to wrap mixed existing agents. | Intentionally lacks a graph runtime, durable execution, built-in tracing/evals/guardrails, a tool catalog, and a deployment platform. |
| LangGraph | A low-level runtime for long-running stateful agents, with durable execution, persistence, streaming, and human-in-the-loop control. | Use LangGraph when execution graphs, resumability, and stateful production runtime behavior are primary. The harness is a much smaller interoperability shell and can wrap a graph only after its template adapter is completed. |
| CrewAI | Crews organize collaborating agents; Flows provide stateful, event-driven workflow structure and execution control. | CrewAI provides higher-level agent/team and workflow concepts. The harness provides only a narrow backend boundary, shared context, memory protocol, and supervisor loop. |
| OpenAI Agents SDK | Agent loops with tools, agent handoffs, input/output guardrails, sessions, and built-in tracing. | The SDK is more batteries-included for constructing and operating agents. The harness supplies no native tools, guardrails, or tracing and focuses on wrapping backends through a provider-neutral protocol. |
| Microsoft Agent Framework | The direct AutoGen/Semantic Kernel successor: agents, session state, explicit functional/graph workflows, middleware, telemetry/integrations, and MCP tool connections. | Microsoft Agent Framework is a broad application framework. The harness is deliberately smaller and has no workflow engine, middleware pipeline, or MCP client. |
| Google ADK | A model- and deployment-agnostic agent framework with tools, context management, multi-agent orchestration, graph workflows, evaluation, and production deployment paths. | ADK covers the agent development lifecycle. The harness is only a portable coordination shell and does not reproduce ADK's tool, evaluation, graph, or deployment capabilities. |
Comparison content is paraphrased from the linked official documentation for clarity and licensing compliance. Capabilities evolve; consult those sources when making a framework decision.
HarnessContext is the state passed between steps: the conversation (messages), transient scratchpad, named artifacts, and tools_state records. It is a plain dataclass with to_dict() / from_dict() serialization.
StepResult is the only vocabulary crossing the loop/backend boundary:
@dataclass
class StepResult:
status: Literal["continue", "done", "error"]
next_agent: str | None = None # supervisor only: who runs next
payload: Any = None # next input or final output
message: str | None = None # human-readable display note
MemoryProvider defines save(session_id, context) and load(session_id). InMemoryProvider and stdlib-backed SQLiteMemoryProvider are included.
from agent_harness_kit import HarnessLoop, InMemoryProvider
from agent_harness_kit.backends.claude_backend import ClaudeBackend
supervisor = ClaudeBackend(
model="claude-opus-4-8",
is_supervisor=True,
agent_names=["researcher", "writer"],
)
loop = HarnessLoop(
memory=InMemoryProvider(),
supervisor=supervisor,
agents={
"researcher": ClaudeBackend(
model="claude-opus-4-8",
system_prompt="You research topics thoroughly.",
),
"writer": ClaudeBackend(
model="claude-opus-4-8",
system_prompt="You write clear, concise prose.",
),
},
max_steps=25,
)
context = loop.run_supervised(
objective="Draft a short blog post about SQLite",
input="Focus on why it is a good fit for small apps.",
session_id="session-1",
)
print(context.messages[-1])
Agents can also be registered incrementally:
loop = HarnessLoop(memory=InMemoryProvider(), supervisor=supervisor)
loop.register_agent("researcher", researcher_backend)
loop.register_agent("writer", writer_backend)
Swap InMemoryProvider() for SQLiteMemoryProvider("agents.db") to persist JSON context across process restarts without changing the loop.
Anything with run_step(self, context: HarnessContext) -> StepResult satisfies AgentBackend; no base class is required because it is a typing.Protocol.
ClaudeBackend and OpenAIBackend are complete reference implementations for single-completion steps and supervisor routing. LangGraphBackend, CrewAIBackend, and StrandsBackend are explicit templates: their constructors validate/lazily import the corresponding SDK, but run_step raises NotImplementedError until you add application-specific context and result mapping.
The harness can sit above multiple framework workers, wrap one whole framework workflow as an opaque worker, or mix both approaches. It never attempts to reproduce LangGraph graph execution, CrewAI's crew/flow model, or Strands' model-driven tool loop.
Install the currently published package from PyPI:
python -m pip install agent-harness-kit
Install only the optional SDK needed by a backend:
python -m pip install "agent-harness-kit[anthropic]" # complete ClaudeBackend
python -m pip install "agent-harness-kit[openai]" # complete OpenAIBackend
python -m pip install "agent-harness-kit[langgraph]" # LangGraph template
python -m pip install "agent-harness-kit[crewai]" # CrewAI template
python -m pip install "agent-harness-kit[strands]" # Strands template
python -m pip install "agent-harness-kit[all]" # every optional SDK
The base install has zero third-party runtime dependencies. Credentials are never bundled; provide them through the SDK/client or environment used by your selected backend.
For local development:
python -m pip install -e ".[dev]"
pytest
Tests use fake in-process supervisors/workers, fake Anthropic and OpenAI clients, and a synthetic Strands module. They require no credentials or network access and pass whether optional framework SDKs are installed or not.
Official documentation used for the capability summary:
These links describe those projects, not endorsements or compatibility guarantees. All comparison prose above is paraphrased from official documentation.
Status: unreleased candidate. This version bump is necessary because the README embedded in already-published PyPI 0.1.0 metadata cannot be changed in place.
0.1.0 to 0.1.1; no core runtime behavior or dependency surface changes.Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
anthropicEnvironment{
"extras": "",
"marker": "extra == \"anthropic\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | anthropic>=0.40.0; extra == "anthropic" | runtime |
openaiEnvironment{
"extras": "",
"marker": "extra == \"openai\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | openai>=1.45.0; extra == "openai" | runtime |
langgraphEnvironment{
"extras": "",
"marker": "extra == \"langgraph\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | langgraph>=0.2.0; extra == "langgraph" | runtime |
crewaiEnvironment{
"extras": "",
"marker": "extra == \"crewai\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | crewai>=0.80.0; extra == "crewai" | runtime |
strands-agentsEnvironment{
"extras": "",
"marker": "extra == \"strands\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | strands-agents>=0.1.0; extra == "strands" | runtime |
anthropicEnvironment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | anthropic>=0.40.0; extra == "all" | runtime |
openaiEnvironment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | openai>=1.45.0; extra == "all" | runtime |
langgraphEnvironment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | langgraph>=0.2.0; extra == "all" | runtime |
crewaiEnvironment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | crewai>=0.80.0; extra == "all" | runtime |
strands-agentsEnvironment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | strands-agents>=0.1.0; extra == "all" | runtime |
pytestEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pytest>=8.0.0; extra == "dev" | runtime |
bdist_wheel · 26.75 KB · Python py3
sdist · 27.99 KB · Python source
Shared repository data · GitHub
Observed since 20 Oct, 22:09 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:daf919de7e6f95f1821c578cee44b28f7f8ca0472eb86df4a41b3b8d83fa0d2b