Skip to content
MindLab-ResearchPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

Repository files navigation

harness-configuration-protocol

Python SDK and CLI for running an agent from a Harness Configuration Protocol (HCP) TOML file.

This package does not implement an agent by itself. It is a Python control layer around this chain:

Python app / hcp CLI -> hcp-sdk -> pi-hcp -> pi-acp -> Pi -> model provider

Use it when you want Python code or scripts to:

  • validate that an HCP TOML file is readable
  • ask pi-hcp to prepare a Pi runtime directory
  • start the prepared ACP agent process
  • create/load an ACP session
  • send a text prompt and collect text chunks from session/update

Package names

What Name
PyPI package harness-configuration-protocol
Python import hcp
CLI command hcp

Status

Current implementation is wrapper mode only:

  • hcp-sdk shells out to pi-hcp --dry-run for runtime preparation.
  • hcp-sdk then launches pi-hcp as the ACP stdio process.
  • Native Python HCP materialization is planned but not implemented.

That means HCP features such as skills, embedded resources, MCP, hooks, model config, and workspace staging are handled by pi-hcp, not by Python code in this repository.

Install

pip install harness-configuration-protocol

For local development:

cd hcp-sdk
pip install -e '.[dev]'

Requirements

Wrapper mode needs:

  • a readable HCP TOML file
  • pi-hcp on PATH, or an explicit --pi-hcp-command / pi_hcp_command
  • pi-acp on PATH, or an explicit --acp-command / acp_command
  • provider environment variables required by your HCP config

Default unit tests do not require Node, Pi, pi-acp, provider credentials, or network access.

Minimal HCP config

Save as hcp.toml or copy examples/minimal-hcp.toml. For a broad all-sections example, see examples/full-hcp.toml:

version = 1

[run]
cwd = "."
agent_dir = ".pi-agent"
offline = false
verbose = false

[env]
files = [".env"]
override = true
required = ["OPENAI_API_KEY"]

[env.set]
PI_SKIP_VERSION_CHECK = "1"

[model]
provider = "openai"
id = "gpt-4o-mini"
api = "openai-completions"
base_url = "https://api.openai.com/v1/"
api_key_env = "OPENAI_API_KEY"
context_window = 128000
max_tokens = 16000

[tools]
allow = []

Then create .env beside it:

OPENAI_API_KEY=sk-...

CLI quickstart

Validate TOML readability:

hcp validate hcp.toml

Ask pi-hcp to prepare the runtime and print redacted metadata:

hcp prepare hcp.toml --json

Run one prompt:

hcp run hcp.toml --prompt "Say hello in one sentence."

Use explicit command paths when pi-hcp or pi-acp are not on PATH:

hcp run hcp.toml \
  --prompt "Say hello" \
  --pi-hcp-command 'node /path/to/pi-hcp/dist/index.js' \
  --acp-command '/path/to/pi-acp/dist/index.js'

Python quickstart

import asyncio
from hcp import connect_agent

async def main() -> None:
    async with connect_agent(
        "hcp.toml",
        pi_hcp_command="pi-hcp",
        acp_command="pi-acp",
    ) as agent:
        await agent.initialize()
        await agent.new_session()
        text = await agent.prompt_text("Say hello in one sentence.")
        print(text)

asyncio.run(main())

API surface

validate_config(path)

Reads the TOML file and checks basic HCP wrapper compatibility:

from hcp import validate_config

config = validate_config("hcp.toml")
print(config.path)
print(config.data)

This is not a full semantic validator. It checks that the file exists, is TOML, is a table, and uses version = 1.

prepare_runtime(path, ...)

Runs pi-hcp --config <path> --dry-run and returns preparation metadata:

from hcp import prepare_runtime

runtime = prepare_runtime(
    "hcp.toml",
    pi_hcp_command="pi-hcp",
    acp_command="pi-acp",
)

print(runtime.cwd)
print(runtime.agent_dir)
print(runtime.acp_command)
print(runtime.to_redacted_dict())

connect_agent(path, ...)

Prepares runtime, starts pi-hcp, connects with agent-client-protocol, and yields an HcpAgentSession:

async with connect_agent("hcp.toml") as agent:
    await agent.initialize()
    session = await agent.new_session()
    text = await agent.prompt_text("Summarize the current workspace.")

Useful methods:

Method Purpose
initialize() Send ACP initialize request
new_session() Create a new ACP session using the prepared cwd
load_session(session_id) Load an existing session id
prompt_text(text, timeout=None) Send a text prompt and return collected assistant text
close() Close ACP connection and stop process

Configuring skills

Yes, HCP configs can provide Pi skills. In wrapper mode, pi-hcp resolves and writes them into Pi settings.

Use existing skill files:

[skills]
enabled = true
paths = [
  "./skills/code-review/SKILL.md",
  "/absolute/path/to/skills/risk/SKILL.md",
]

Or embed a skill directly in the HCP config. See also examples/skills-hcp.toml and examples/full-hcp.toml:

[resources]
embedded_dir = ".hcp-embedded"

[[resources.embedded]]
kind = "skill"
path = ".pi/skills/risk/SKILL.md"
encoding = "utf-8"
content = """
# Risk Skill
Use this skill only for high-risk fixture validation.
"""
sha256 = "<sha256-of-content>"

After preparation, pi-hcp materializes embedded skills under embedded_dir and adds the resulting SKILL.md path to Pi settings.json.

Rules of thumb:

  • Use [skills].paths for normal local skills.
  • Use [[resources.embedded]] kind = "skill" when the HCP file should carry the skill content.
  • Prefer absolute paths in generated configs. Relative paths are resolved by pi-hcp against the configured run context.
  • Keep one skill per directory with a SKILL.md file.

Other common HCP sections

System prompts and append prompts

[resources]
system_prompt_path = "sys.md"
append_system_prompt_paths = ["append.md"]
context_files = false

MCP config

[mcp]
config_path = "base-mcp.json"
imports = ["cursor"]

[mcp.settings]
toolPrefix = "risk"

[mcp.servers.echo]
command = "node"
args = ["server.js"]
cwd = "server-cwd"

Hooks

[hooks.PreToolUse.audit]
matcher = "bash"
command = "./hooks/audit.sh"
timeout = 2
run_async = true

Session snapshot import

[session]
snapshot_json = '''{"version":1,"id":"seed-session","messages":[{"role":"system","content":"seeded"}]}'''

Workspace staging

[workspace]
root = "workspace-root"

[[workspace.entries]]
name = "data"
source = "local:data.txt"
target = "data.txt"
mode = "copy"

Environment and secrets

You can pass extra environment variables from Python:

async with connect_agent(
    "hcp.toml",
    env={"OPENAI_API_KEY": "sk-..."},
    secrets=["sk-..."],
) as agent:
    ...

secrets are redacted from SDK subprocess diagnostics. They are not a secret manager. Do not commit .env files or TOML files containing API keys.

Error model

The SDK raises HcpConfigError for config-read failures and HcpLaunchError for wrapper/launch failures. Both inherit from HcpError.

Common failures:

Symptom Likely cause
Unable to execute pi-hcp command pi-hcp path is wrong or not on PATH
pi-hcp dry-run failed HCP semantic/config/provider-env error reported by pi-hcp
did not return JSON wrong command passed as pi-hcp, or wrapper printed non-JSON during dry run
ACP connection failed pi-hcp launched but pi-acp/Pi failed during startup
empty prompt text provider returned no assistant chunks, runtime notices were filtered, or prompt failed upstream

Development

Run deterministic tests:

uv run pytest

Run lint/type-oriented checks if available in your environment:

uv run ruff check .

Live full-chain tests

Live tests are opt-in and may consume API credits. They verify:

hcp-sdk -> pi-hcp -> pi-acp -> Pi -> provider

Example with Novita:

cd /home/aka/harness-mono/hcp-sdk

export HCP_SDK_RUN_LIVE=1
export HCP_SDK_RUN_LIVE_PROVIDER=1
export HCP_SDK_LIVE_PI_HCP_COMMAND='node /home/aka/harness-mono/pi-hcp/dist/index.js'
export HCP_SDK_LIVE_ACP_COMMAND='/home/aka/harness-mono/reference-only/pi-acp/dist/index.js'
export NOVITA_API_KEY='...'
export NOVITA_BASE_URL='https://api.novita.ai/openai/v1/'
export NOVITA_MODEL='deepseek/deepseek-v4-flash'
export NOVITA_CONTEXT_WINDOW='128000'
export NOVITA_MAX_TOKENS='32000'

uv run pytest tests/test_live_full_chain.py

Before launching pi-hcp, pi-acp, or Pi, provider-backed tests run a small OpenAI-compatible chat/completions preflight against the configured provider. 401 or 403 means provider credential, endpoint, or model-access failure before HCP launch. Raw API keys are redacted from diagnostics.

Real-config high-risk live tests

Real-config tests exercise riskier HCP combinations: env/model, runtime artifacts, packages, resources, skills, MCP, hooks, session import, interaction, and failure diagnostics.

Prep-only run, no provider prompt:

cd /home/aka/harness-mono/hcp-sdk

export HCP_SDK_RUN_LIVE=1
export HCP_SDK_RUN_REAL_CONFIG=1
export HCP_SDK_LIVE_PI_HCP_COMMAND='node /home/aka/harness-mono/pi-hcp/dist/index.js'
export HCP_SDK_LIVE_ACP_COMMAND='/home/aka/harness-mono/reference-only/pi-acp/dist/index.js'

uv run pytest tests/test_live_real_config.py::test_real_config_high_risk_preparation_artifacts \
  tests/test_live_real_config.py::test_real_config_failure_diagnostics_are_contextual_and_redacted

Provider-backed run:

cd /home/aka/harness-mono/hcp-sdk

export HCP_SDK_RUN_LIVE=1
export HCP_SDK_RUN_REAL_CONFIG=1
export HCP_SDK_RUN_LIVE_PROVIDER=1
export HCP_SDK_LIVE_PI_HCP_COMMAND='node /home/aka/harness-mono/pi-hcp/dist/index.js'
export HCP_SDK_LIVE_ACP_COMMAND='/home/aka/harness-mono/reference-only/pi-acp/dist/index.js'
export NOVITA_API_KEY='...'
export NOVITA_BASE_URL='https://api.novita.ai/openai/v1/'
export NOVITA_MODEL='deepseek/deepseek-v4-flash'
export NOVITA_CONTEXT_WINDOW='128000'
export NOVITA_MAX_TOKENS='32000'

uv run pytest tests/test_live_real_config.py

Use your own config:

export HCP_SDK_LIVE_CONFIG=/path/to/hcp.toml
# or
export PI_HCP_LIVE_CONFIG=/path/to/hcp.toml

User-provided config files are not printed in diagnostics. Diagnostics include scenario/layer markers such as [scenario:interaction][layer:provider], and known secret values are redacted.

Related documents

Current limitations

Implemented:

  • package metadata and CLI entrypoint
  • TOML readability validation
  • wrapper-mode pi-hcp --dry-run preparation
  • ACP connection/session helper
  • text prompt collection from session/update
  • redacted subprocess diagnostics

Not implemented natively in Python yet:

  • full HCP schema validation
  • native runtime preparation
  • native skill/resource materialization
  • native session import/export helpers
  • workspace staging backend interface
  • interactive terminal/file/tool callbacks beyond text collection

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages