Skip to main content

Python SDK for H Company's Computer-Use Agents: autonomous agents powered by Holo.

Project description

Computer-Use Agents

PyPI Python versions License: MIT

Python SDK for H Company's Computer-Use Agents.

Documentation  ·  Get an API key  ·  PyPI  ·  TypeScript SDK  ·  H Company

Installation

pip install hai-agents

Add the optional command-line tools with the cli extra:

pip install "hai-agents[cli]"

Python 3.10 or newer is required. Get an API key at platform.hcompany.ai/settings/api-keys and export it:

export HAI_API_KEY=hk-...

Quickstart

Launch the built-in h/web-surfer-pro agent, which ships with its own browser, and describe the task in plain language. run_session polls until the agent finishes and returns the final answer.

from hai_agents import Client

client = Client()  # reads HAI_API_KEY from the environment

result = client.run_session(
    agent="h/web-surfer-pro",
    messages="What are the top 3 stories on Hacker News right now?",
)

print(result.status)  # a settled state: "idle" on EU (the default), "completed" on US
print(result.answer)

result is a SessionRunResult: id, status, answer, the accumulated events, and final_changes.

How a session works

A session is one run of an agent against a task. It moves through a small set of states: pending, running, and then a settled state such as completed, idle, failed, timed_out, or interrupted.

You drive a session two ways. run_session creates it and blocks until it settles, which suits one-shot tasks. start_session creates it and returns a handle right away, so you can read and steer the agent while it works.

session = client.start_session(
    agent="h/web-surfer-pro",
    messages="Find the top story on Hacker News",
)

print(session.id)
result = session.wait_for_completion()
print(result.status, result.answer)

Watch and steer a running session

A handle bound to the session id exposes the full lifecycle. Read the agent's progress at three levels of detail:

session.status()               # cheap snapshot: state, step count, token usage
session.changes(from_index=0)  # new events and the final answer, long-polled
session.get()                  # the full Session resource

While the session is not in a terminal state, you can intervene:

session.send_message({"type": "user_message", "message": "Only consider the last 24 hours"})
session.pause()         # halt with state preserved
session.resume()        # continue where it left off
session.force_answer()  # stop exploring and answer from what it has
session.cancel()        # stop for good; ends in "interrupted"

send_message redirects the agent on its next step. Sending a message to an idle session also wakes it.

Multi-turn sessions

By default a session ends as soon as the agent answers. Set idle_timeout_s to keep it open: after each answer the session goes idle and waits that long for your next message, carrying its full context and browser state across turns.

session = client.start_session(
    agent="h/web-surfer-pro",
    idle_timeout_s=600,
    messages="Find the top story on Hacker News",
)
first = session.wait_for_completion()

session.send_message({"type": "user_message", "message": "Now summarize its comments"})
second = session.wait_for_completion()

Structured output

Pass a pydantic model as answer_schema and the agent's final answer comes back as a validated instance. The model's JSON schema is sent as the agent's answer format; the raw wire value stays at result.final_changes.answer.

from pydantic import BaseModel
from hai_agents import Client

class Job(BaseModel):
    title: str
    company: str

class Jobs(BaseModel):
    jobs: list[Job]

client = Client()
result = client.run_session(
    agent="h/web-surfer-pro",
    messages="Find 3 open ML engineering roles in Paris.",
    answer_schema=Jobs,
)

for job in result.answer.jobs:  # result.answer is a Jobs instance
    print(job.title, "@", job.company)

A completed answer that does not match the schema raises AnswerValidationError, with the raw payload on .raw. Sessions that end without completing return their raw answer untouched.

Custom tools

Expose your own Python functions to the agent. Pass them to run_session and the polling loop runs each one when the agent calls it, then posts the result back so the session continues. Any function with typed parameters and a docstring works; the input schema is derived from the signature.

from hai_agents import Client

def get_weather(city: str) -> str:
    """Get the current weather for a city."""
    return f"Sunny in {city}"

client = Client()

result = client.run_session(
    agent="h/web-surfer-pro",
    messages="What should I wear in Paris today?",
    tools=[get_weather],
)

Use the @tool decorator to override the name or description:

from hai_agents import tool

@tool(name="lookup_order", description="Look up an order by its id.")
def lookup(order_id: str) -> dict:
    return {"id": order_id, "status": "shipped"}

A tool that raises is reported to the agent as a tool error rather than crashing the run. With AsyncClient, tools may be async def.

Browser profiles and vaults

Start a session on a browser that already knows the user. A browser profile restores saved cookies and storage from an earlier session, and a vault lets the agent sign in to sites with secrets that never enter its context. Bind both through per-run overrides:

result = client.run_session(
    agent="h/web-surfer-pro",
    messages="Open my dashboard and report any new alerts",
    overrides={
        "agent.environments[kind=web].browser_profile_id": "<profile-id>",
        "agent.environments[kind=web].vault_id": "<vault-id>",
    },
)

Async

AsyncClient mirrors Client for asyncio. Every session method is a coroutine.

import asyncio
from hai_agents import AsyncClient

async def main():
    client = AsyncClient()
    result = await client.run_session(
        agent="h/web-surfer-pro",
        messages="What are the top 3 stories on Hacker News right now?",
    )
    print(result.answer)

asyncio.run(main())

Inspect and share sessions

List past sessions and create a public replay link:

page = client.sessions.list_sessions(size=10)
for summary in page.items:
    print(summary.id, summary.status)

link = client.sessions.share_session("<session-id>")
print(link.share_url)

Regions and configuration

The client targets the EU region by default. Point it at the US region or a custom URL, and override the API key in code when you do not want to use the environment variable:

from hai_agents import Client, HaiAgentsEnvironment

client = Client(environment=HaiAgentsEnvironment.US)
# or
client = Client(base_url="https://agp.hcompany.ai", api_key="hk-...")

Errors

from hai_agents import AnswerValidationError, UnprocessableEntityError
from hai_agents.core import ApiError

ApiError is the base for HTTP failures and carries .status_code and .body. UnprocessableEntityError is the 422 raised when a request fails validation. AnswerValidationError is raised when a completed answer does not match answer_schema, with the unparsed value on .raw.

Webhooks

Verify the signature on an incoming webhook before trusting it:

from hai_agents import verify_webhook, WebhookVerificationError

event = verify_webhook(request_body, signature, timestamp, secret)
print(event.type, event.data)

Command line

The cli extra installs the hai command for driving agents from your terminal:

hai login                 # browser sign-in, stores a key in ~/.config/hai/.env
hai run "What's the top story on Hacker News?"
hai sessions list
hai sessions watch <session-id>
hai mcp install           # add the hai-agents MCP server to Cursor, VS Code, Claude Code, ...

Credentials resolve from --api-key, then HAI_API_KEY, then a local .env, then ~/.config/hai/.env. Run hai --help for the full command set.

Documentation

Guides, core concepts, and the full API reference live at hub.hcompany.ai/computer-use-agents.

License

MIT

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

hai_agents-1.0.4.tar.gz (1.9 MB view details)

Uploaded Source

Built Distribution

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

hai_agents-1.0.4-py3-none-any.whl (191.0 kB view details)

Uploaded Python 3

File details

Details for the file hai_agents-1.0.4.tar.gz.

File metadata

  • Download URL: hai_agents-1.0.4.tar.gz
  • Upload date:
  • Size: 1.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for hai_agents-1.0.4.tar.gz
Algorithm Hash digest
SHA256 b8d26bb260e9536c051de6e83f4f0d44090c0284a9191da33f7c8b52e34198ce
MD5 f735008494b7121469fb754d8c07e2c1
BLAKE2b-256 6936b6ec75b96d943932d7bed79c3227d34e2368fc2cf4111fd810787adf1b36

See more details on using hashes here.

Provenance

The following attestation bundles were made for hai_agents-1.0.4.tar.gz:

Publisher: publish.yml on hcompai/hai-agents-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hai_agents-1.0.4-py3-none-any.whl.

File metadata

  • Download URL: hai_agents-1.0.4-py3-none-any.whl
  • Upload date:
  • Size: 191.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for hai_agents-1.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 eaa2a4d81585f1311c56ad6d8939117ed16acb16e965c296a7504df4ec85f107
MD5 812114f7b998eb06a1e13961cf573be5
BLAKE2b-256 9cb567734e668e27021cee86f9a3d5794ded2105b92c2050b970255ca4d46f8f

See more details on using hashes here.

Provenance

The following attestation bundles were made for hai_agents-1.0.4-py3-none-any.whl:

Publisher: publish.yml on hcompai/hai-agents-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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