Skip to main content

Python SDK for controlling Happy agent sessions

Project description

happy-engineering-sdk

PyPI version Python versions License: MIT

Python SDK for controlling Happy agent sessions.

Installation

pip install happy-engineering-sdk

Credentials

The SDK supports three ways to supply credentials.

1. Environment variables (recommended for containers)

export HAPPY_SERVER_URL=https://api.happy.engineering
export HAPPY_TOKEN=eyJ...
export HAPPY_SECRET=DroKzo0w...==

HAPPY_TOKEN is the bearer token and HAPPY_SECRET is the raw base64 machineKey string from your access.key file.

2. Key file (default for local use)

Download access.key (or agent.key) from the Happy dashboard and place it at:

~/.happy/access.key   # written by the Happy CLI
~/.happy/agent.key    # legacy location

The SDK understands both formats — the CLI-written access.key format (encryption.machineKey) and the older agent.key format (secret).

Set the server URL:

export HAPPY_SERVER_URL=https://api.happy.engineering

3. Inline kwargs

client = HappyClient(
    server_url="https://api.happy.engineering",
    token="eyJ...",
    secret_b64="DroKzo0w...==",
)

Quick start — async (HappyClient)

import asyncio
from happy_sdk import HappyClient

async def main():
    client = HappyClient()          # reads ~/.happy/agent.key + HAPPY_SERVER_URL
    session_id = await client.run_task(
        machine_id="my-machine",
        directory="/home/user/project",
        prompt="Summarise this week's PRs",
    )
    print(f"Task complete — session {session_id}")

asyncio.run(main())

Using environment variables:

client = HappyClient.from_env()    # reads HAPPY_TOKEN, HAPPY_SECRET, HAPPY_SERVER_URL

Quick start — sync (SyncHappyClient)

For Django management commands, CLI scripts, or any sync context — use SyncHappyClient. It has the same API as HappyClient but wraps every call with asyncio.run() internally so you never touch async machinery:

from happy_sdk import SyncHappyClient

# From environment variables
client = SyncHappyClient.from_env()

session_id = client.run_task(
    machine_id="my-machine",
    directory="/home/user/project",
    prompt="Summarise this week's PRs",
)
print(f"Task complete — session {session_id}")

All three constructor styles work with SyncHappyClient:

# From env vars
client = SyncHappyClient.from_env()
client = SyncHappyClient.from_env(server_url="https://...")

# From inline kwargs
client = SyncHappyClient(server_url="...", token="...", secret_b64="...")

# From key file
client = SyncHappyClient(server_url="...", credentials_path="~/.happy/access.key")

Manual session lifecycle

import asyncio
from happy_sdk import HappyClient

async def main():
    client = HappyClient()

    session_id = await client.spawn_session(
        machine_id="my-machine",
        directory="/home/user/project",
    )
    await client.send_message(session_id, "Hello")
    await client.wait_for_turn_completion(session_id)
    messages = await client.get_messages(session_id)
    await client.stop_session(session_id)

asyncio.run(main())

API reference

HappyClient (async) / SyncHappyClient (sync)

Both classes expose identical method signatures. HappyClient methods are async; SyncHappyClient methods are regular (blocking) functions.

Constructors

Constructor Description
HappyClient(server_url=None, credentials_path=None, token=None, secret_b64=None) File or kwargs. token+secret_b64 take precedence over credentials_path. server_url falls back to HAPPY_SERVER_URL.
HappyClient.from_env(server_url=None) Reads HAPPY_TOKEN, HAPPY_SECRET, HAPPY_SERVER_URL. Raises AuthenticationError if any are missing.
SyncHappyClient(...) Same arguments as HappyClient.
SyncHappyClient.from_env(server_url=None) Same as HappyClient.from_env.

Session lifecycle

Method Signature Description
spawn_session (machine_id, directory, agent="claude", create_dir=False) → str Create a new agent session — returns the session ID
stop_session (session_id) Stop a running session
delete_session (session_id) Permanently delete a session

Messaging

Method Signature Description
send_message (session_id, text, permission_mode="yolo") Send a message to an active session

Waiting

Method Signature Description
wait_for_turn_completion (session_id, timeout_seconds=300) Block until the agent finishes its current turn
wait_for_idle (session_id, timeout_seconds=300) Block until the session enters an idle state

Query

Method Signature Description
list_sessions (active_only=False) → list[Session] List all (or only active) sessions
get_session (session_id) → Session Fetch a single session
get_messages (session_id) → list[Message] Fetch all messages for a session
list_machines (active_only=False) → list[Machine] List all (or only active) machines
get_machine (machine_id) → Machine Fetch a single machine

Convenience

Method Signature Description
run_task (machine_id, directory, prompt, agent="claude", timeout_seconds=600) → str Spawn, send, wait, stop — returns session ID

Cleanup

Method Signature Description
close () Release any held resources (no-op in the current implementation)

Types

Type Fields
Session id: str, active: bool, created_at: int, metadata: dict, agent_state: str | None
Machine id: str, active: bool, metadata: dict
Message id: str, seq: int, content: dict, created_at: int
Agent Literal["claude"]
PermissionMode Literal["yolo"]

Exceptions

All exceptions inherit from HappyError.

Exception Raised when
AuthenticationError Credentials missing, expired, or malformed
MachineOfflineError Target machine is not connected to the server
SpawnError Session spawn failed
TimeoutError Wait exceeded the specified timeout
EncryptionError Encrypt or decrypt operation failed
ConnectionError Socket connection failed or disconnected unexpectedly

License

MIT — see LICENSE.

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

happy_engineering_sdk-0.2.0.tar.gz (27.8 kB view details)

Uploaded Source

Built Distribution

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

happy_engineering_sdk-0.2.0-py3-none-any.whl (13.4 kB view details)

Uploaded Python 3

File details

Details for the file happy_engineering_sdk-0.2.0.tar.gz.

File metadata

  • Download URL: happy_engineering_sdk-0.2.0.tar.gz
  • Upload date:
  • Size: 27.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for happy_engineering_sdk-0.2.0.tar.gz
Algorithm Hash digest
SHA256 6d46d09dae182a709957fa142f83ddd371a1f7168abc920d0d311ec119b24d22
MD5 f5dcf1cf7f67d0cc3e0706a3532aadd7
BLAKE2b-256 4ff01e32b439cab2ca81eb68ebed3108aac8f7a077331de978621f02d2083d36

See more details on using hashes here.

File details

Details for the file happy_engineering_sdk-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for happy_engineering_sdk-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e51ecc890fd68e36d8d8de46222e0d82c4d2c8e243a38a15c24361bb0a22d55a
MD5 deb038d903dd71db54e4a77b927dbacd
BLAKE2b-256 5bdd6493298655ce6b1150a62dd3dce30eea471f3e556321fbcb70bd26973827

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