{"id":51626232,"url":"https://github.com/hcompai/hai-agents-python","last_synced_at":"2026-07-13T01:32:36.532Z","repository":{"id":367362249,"uuid":"1252416972","full_name":"hcompai/hai-agents-python","owner":"hcompai","description":"Python SDK for H Company's Computer-Use Agent API","archived":false,"fork":false,"pushed_at":"2026-07-03T11:29:19.000Z","size":3766,"stargazers_count":30,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-03T12:22:10.166Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://hub.hcompany.ai/computer-use-agents","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hcompai.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-28T13:54:41.000Z","updated_at":"2026-07-03T09:59:45.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/hcompai/hai-agents-python","commit_stats":null,"previous_names":["hcompai/hai-agents-python"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/hcompai/hai-agents-python","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hcompai%2Fhai-agents-python","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hcompai%2Fhai-agents-python/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hcompai%2Fhai-agents-python/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hcompai%2Fhai-agents-python/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hcompai","download_url":"https://codeload.github.com/hcompai/hai-agents-python/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hcompai%2Fhai-agents-python/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35407393,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-12T02:00:06.386Z","response_time":87,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-13T01:32:36.374Z","updated_at":"2026-07-13T01:32:36.514Z","avatar_url":"https://github.com/hcompai.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://github.com/hcompai/hai-agents-python/blob/main/assets/banner-dark.gif?raw=true\" /\u003e\n    \u003cimg src=\"https://github.com/hcompai/hai-agents-python/blob/main/assets/banner-light.gif?raw=true\" alt=\"Computer-Use Agents\" width=\"700\" /\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://pypi.org/project/hai-agents/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/v/hai-agents.svg\" alt=\"PyPI\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://pypi.org/project/hai-agents/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/pyversions/hai-agents.svg\" alt=\"Python versions\" /\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-MIT-yellow.svg\" alt=\"License: MIT\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  Python SDK for \u003ca href=\"https://hcompany.ai\"\u003eH Company\u003c/a\u003e's \u003ca href=\"https://hub.hcompany.ai/computer-use-agents\"\u003eComputer-Use Agents\u003c/a\u003e.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cb\u003e\u003ca href=\"https://hub.hcompany.ai/computer-use-agents\"\u003eDocumentation\u003c/a\u003e\u003c/b\u003e\n  \u0026nbsp;·\u0026nbsp;\n  \u003ca href=\"https://platform.hcompany.ai/settings/api-keys\"\u003eGet an API key\u003c/a\u003e\n  \u0026nbsp;·\u0026nbsp;\n  \u003ca href=\"https://pypi.org/project/hai-agents/\"\u003ePyPI\u003c/a\u003e\n  \u0026nbsp;·\u0026nbsp;\n  \u003ca href=\"https://github.com/hcompai/hai-agents-ts\"\u003eTypeScript SDK\u003c/a\u003e\n  \u0026nbsp;·\u0026nbsp;\n  \u003ca href=\"https://hcompany.ai\"\u003eH Company\u003c/a\u003e\n\u003c/p\u003e\n\n## Installation\n\n```bash\npip install hai-agents\n```\n\nAdd the optional command-line tools with the `cli` extra:\n\n```bash\npip install \"hai-agents[cli]\"\n```\n\nPython 3.10 or newer is required. Get an API key at [platform.hcompany.ai/settings/api-keys](https://platform.hcompany.ai/settings/api-keys) and export it:\n\n```bash\nexport HAI_API_KEY=hk-...\n```\n\n## Quickstart\n\nLaunch 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.\n\n```python\nfrom hai_agents import Client\n\nclient = Client()\n\nresult = client.run_session(\n    agent=\"h/web-surfer-pro\",\n    messages=\"What are the top 3 stories on Hacker News right now?\",\n)\n\nprint(result.status)\nprint(result.answer)\n```\n\n`Client()` reads `HAI_API_KEY` from the environment.\n\n`result` is a `SessionRunResult`: `id`, `status`, `answer`, the accumulated `events`, and `final_changes`.\n\n## How a session works\n\nA 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`.\n\nYou 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.\n\n```python\nsession = client.start_session(\n    agent=\"h/web-surfer-pro\",\n    messages=\"Find the top story on Hacker News\",\n)\n\nprint(session.id)\nresult = session.wait_for_completion()\nprint(result.status, result.answer)\n```\n\n## Watch and steer a running session\n\nA handle bound to the session `id` exposes the full lifecycle. Read the agent's progress at three levels of detail:\n\n```python\nsession.status()\nsession.changes(from_index=0)\nsession.get()\n```\n\n`status()` is a cheap snapshot with the state, step count, and token usage. `changes(from_index=0)` long-polls for new events and the final answer. `get()` returns the full Session resource.\n\nWhile the session is not in a terminal state, you can intervene:\n\n```python\nsession.send_message({\"type\": \"user_message\", \"message\": \"Only consider the last 24 hours\"})\nsession.pause()\nsession.resume()\nsession.force_answer()\nsession.cancel()\n```\n\n`send_message` redirects the agent on its next step and wakes an `idle` session. `pause` halts with state preserved until `resume`. `force_answer` makes the agent stop exploring and answer from what it has. `cancel` ends the session as `interrupted`.\n\n## Multi-turn sessions\n\nBy 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.\n\n```python\nsession = client.start_session(\n    agent=\"h/web-surfer-pro\",\n    idle_timeout_s=600,\n    messages=\"Find the top story on Hacker News\",\n)\nfirst = session.wait_for_completion()\n\nsession.send_message({\"type\": \"user_message\", \"message\": \"Now summarize its comments\"})\nsecond = session.wait_for_completion()\n```\n\n## Structured output\n\nPass 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`.\n\n```python\nfrom pydantic import BaseModel\nfrom hai_agents import Client\n\nclass Job(BaseModel):\n    title: str\n    company: str\n\nclass Jobs(BaseModel):\n    jobs: list[Job]\n\nclient = Client()\nresult = client.run_session(\n    agent=\"h/web-surfer-pro\",\n    messages=\"Find 3 open ML engineering roles in Paris.\",\n    answer_schema=Jobs,\n)\n\nfor job in result.answer.jobs:\n    print(job.title, \"@\", job.company)\n```\n\nA 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.\n\n## Custom tools\n\nExpose 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.\n\n```python\nfrom hai_agents import Client\n\ndef get_weather(city: str) -\u003e str:\n    \"\"\"Get the current weather for a city.\"\"\"\n    return f\"Sunny in {city}\"\n\nclient = Client()\n\nresult = client.run_session(\n    agent=\"h/web-surfer-pro\",\n    messages=\"What should I wear in Paris today?\",\n    tools=[get_weather],\n)\n```\n\nUse the `@tool` decorator to override the name or description:\n\n```python\nfrom hai_agents import tool\n\n@tool(name=\"lookup_order\", description=\"Look up an order by its id.\")\ndef lookup(order_id: str) -\u003e dict:\n    return {\"id\": order_id, \"status\": \"shipped\"}\n```\n\nA tool that raises is reported to the agent as a tool error rather than crashing the run. With `AsyncClient`, tools may be `async def`.\n\n### Prebuilt: one-time passwords (2FA)\n\n`hai_agents_tools` ships ready-made tools. `otp_tool` lets the agent ask for a one-time password, verification code, or confirmation link when a login or signup step needs one. Without a handler it prompts on stdin; `imap_otp_handler` reads the code straight from a mailbox over IMAP (for Gmail, use an app password).\n\n```python\nimport os\n\nfrom hai_agents import Client\nfrom hai_agents_tools import imap_otp_handler, otp_tool\n\nhandler = imap_otp_handler(\n    host=\"imap.gmail.com\",\n    username=\"agent-inbox@gmail.com\",\n    password=os.environ[\"GMAIL_APP_PASSWORD\"],\n)\n\nclient = Client()\nresult = client.run_session(\n    agent=\"h/web-surfer-pro\",\n    messages=\"Log in to example.com and check for new notifications\",\n    tools=[otp_tool(handler)],\n)\n```\n\nLike every custom tool, the handler runs entirely in your process: the IMAP credentials never leave your machine, and the agent only receives the single extracted code or link -- never mailbox contents.\n\n## Browser profiles and vaults\n\nStart a session on a browser that already knows the user. A [browser profile](https://hub.hcompany.ai/computer-use-agents/browser-profiles) restores saved cookies and storage from an earlier session, and a [vault](https://hub.hcompany.ai/computer-use-agents/vaults) lets the agent sign in to sites with secrets that never enter its context. Bind both through per-run overrides:\n\n```python\nresult = client.run_session(\n    agent=\"h/web-surfer-pro\",\n    messages=\"Open my dashboard and report any new alerts\",\n    overrides={\n        \"agent.environments[kind=web].browser_profile_id\": \"\u003cprofile-id\u003e\",\n        \"agent.environments[kind=web].vault_id\": \"\u003cvault-id\u003e\",\n    },\n)\n```\n\n## Async\n\n`AsyncClient` mirrors `Client` for asyncio. Every session method is a coroutine.\n\n```python\nimport asyncio\nfrom hai_agents import AsyncClient\n\nasync def main():\n    client = AsyncClient()\n    result = await client.run_session(\n        agent=\"h/web-surfer-pro\",\n        messages=\"What are the top 3 stories on Hacker News right now?\",\n    )\n    print(result.answer)\n\nasyncio.run(main())\n```\n\n## Inspect and share sessions\n\nList past sessions and create a public replay link:\n\n```python\npage = client.sessions.list_sessions(size=10)\nfor summary in page.items:\n    print(summary.id, summary.status)\n\nlink = client.sessions.share_session(\"\u003csession-id\u003e\")\nprint(link.share_url)\n```\n\n## Regions and configuration\n\nThe client targets the EU region by default; pass `environment` to use the US region instead:\n\n```python\nfrom hai_agents import Client, HaiAgentsEnvironment\n\nclient = Client(environment=HaiAgentsEnvironment.US)\n```\n\n`Client` also accepts a custom `base_url`, and an `api_key` when you do not want to use the environment variable:\n\n```python\nclient = Client(base_url=\"https://agp.hcompany.ai\", api_key=\"hk-...\")\n```\n\n## Errors\n\n```python\nfrom hai_agents import AnswerValidationError, UnprocessableEntityError\nfrom hai_agents.core import ApiError\n```\n\n`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`.\n\n## Webhooks\n\nVerify the signature on an incoming webhook before trusting it:\n\n```python\nfrom hai_agents import verify_webhook, WebhookVerificationError\n\nevent = verify_webhook(request_body, signature, timestamp, secret)\nprint(event.type, event.data)\n```\n\n## Command line\n\nThe `cli` extra installs the `hai` command for driving agents from your terminal:\n\n```bash\nhai login\nhai run \"What's the top story on Hacker News?\"\nhai sessions list\nhai sessions watch \u003csession-id\u003e\nhai mcp install\n```\n\n`hai login` signs in through the browser and stores a key in `~/.config/hai/.env`. `hai mcp install` adds the hai-agents MCP server to Cursor, VS Code, Claude Code, and other MCP clients. 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.\n\n## Documentation\n\nGuides, core concepts, and the full API reference live at **[hub.hcompany.ai/computer-use-agents](https://hub.hcompany.ai/computer-use-agents)**.\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhcompai%2Fhai-agents-python","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhcompai%2Fhai-agents-python","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhcompai%2Fhai-agents-python/lists"}