237 lines
7.2 KiB
Markdown
237 lines
7.2 KiB
Markdown
# Hamming plugin for LiveKit Agents
|
|
|
|
Post-call monitoring and session export for LiveKit Agents with Hamming.
|
|
|
|
## Installation
|
|
|
|
Install the plugin from a checked out repository or extracted source archive:
|
|
|
|
```bash
|
|
python -m pip install ./livekit-plugins/livekit-plugins-hamming
|
|
```
|
|
|
|
## Pre-requisites
|
|
|
|
You will need Hamming credentials before configuring the plugin.
|
|
|
|
- `HAMMING_API_KEY`
|
|
- `HAMMING_EXTERNAL_AGENT_ID`
|
|
|
|
Credentials can be passed directly or through environment variables.
|
|
|
|
## Usage
|
|
|
|
```python
|
|
import os
|
|
|
|
from livekit.agents import AgentSession, JobContext
|
|
from livekit.plugins import hamming
|
|
|
|
|
|
async def entrypoint(ctx: JobContext) -> None:
|
|
await ctx.connect()
|
|
|
|
hamming.configure_hamming(
|
|
api_key=os.environ["HAMMING_API_KEY"],
|
|
external_agent_id=os.environ["HAMMING_EXTERNAL_AGENT_ID"],
|
|
recording={"mode": "session_audio"},
|
|
)
|
|
|
|
session = AgentSession()
|
|
hamming.attach_session(
|
|
session,
|
|
job_ctx=ctx,
|
|
customer_metadata={
|
|
"deployment": {
|
|
"environment": "prod",
|
|
"prompt_version": "v17",
|
|
},
|
|
"experiment": {
|
|
"variant": "B",
|
|
},
|
|
},
|
|
external_links=[
|
|
{
|
|
"label": "CRM Contact",
|
|
"url": "https://crm.example.com/contact/123",
|
|
"source": "salesforce",
|
|
}
|
|
],
|
|
session_mode="testing",
|
|
)
|
|
```
|
|
|
|
## Unified Responsibilities
|
|
|
|
The Hamming plugin is intentionally focused on one responsibility:
|
|
|
|
- post-call session export for Call Review and testing workflows
|
|
|
|
Use `attach_session(...)` for per-call review/testing context:
|
|
|
|
- `customer_metadata`
|
|
- `external_links`
|
|
- `session_mode`
|
|
|
|
## Call Review And Testing Fields
|
|
|
|
### `customer_metadata`
|
|
|
|
Use `customer_metadata` for filterable customer-owned metadata:
|
|
|
|
```python
|
|
hamming.attach_session(
|
|
session,
|
|
job_ctx=ctx,
|
|
customer_metadata={
|
|
"deployment": {"environment": "prod"},
|
|
"experiment": {"variant": "B"},
|
|
},
|
|
)
|
|
```
|
|
|
|
### `external_links`
|
|
|
|
Use `external_links` for click-through operator links:
|
|
|
|
```python
|
|
hamming.attach_session(
|
|
session,
|
|
job_ctx=ctx,
|
|
external_links=[
|
|
{
|
|
"label": "CRM Contact",
|
|
"url": "https://crm.example.com/contact/123",
|
|
"source": "salesforce",
|
|
"description": "Primary customer record",
|
|
}
|
|
],
|
|
)
|
|
```
|
|
|
|
### `session_mode`
|
|
|
|
Use `session_mode="testing"` when the call is part of a testing workflow:
|
|
|
|
```python
|
|
hamming.attach_session(
|
|
session,
|
|
job_ctx=ctx,
|
|
session_mode="testing",
|
|
)
|
|
```
|
|
|
|
## Recording Modes
|
|
|
|
The plugin supports explicit recording modes through `configure_hamming(recording=...)`.
|
|
If `recording` is omitted, the plugin exports monitoring payloads only and does not start or resolve recordings.
|
|
|
|
- `none`
|
|
- Send monitoring payload only.
|
|
- `session_audio`
|
|
- Use LiveKit session recording and inline `recording_capture` on the final `/collect` payload.
|
|
- `participant_egress`
|
|
- Start managed LiveKit participant egress and send dual-track recording URLs derived from deterministic output paths.
|
|
- `room_composite`
|
|
- Start managed LiveKit room composite egress and send a single `recording_url` derived from a deterministic output path.
|
|
|
|
### Session Audio (Default Simple Path)
|
|
|
|
```python
|
|
hamming.configure_hamming(
|
|
api_key=os.environ["HAMMING_API_KEY"],
|
|
external_agent_id=os.environ["HAMMING_EXTERNAL_AGENT_ID"],
|
|
recording={"mode": "session_audio"},
|
|
)
|
|
```
|
|
|
|
### Managed Participant Egress
|
|
|
|
```python
|
|
hamming.configure_hamming(
|
|
api_key=os.environ["HAMMING_API_KEY"],
|
|
external_agent_id=os.environ["HAMMING_EXTERNAL_AGENT_ID"],
|
|
recording={
|
|
"mode": "participant_egress",
|
|
"livekit": {
|
|
"url": os.environ["LIVEKIT_URL"],
|
|
"api_key": os.environ["LIVEKIT_API_KEY"],
|
|
"api_secret": os.environ["LIVEKIT_API_SECRET"],
|
|
},
|
|
"s3": {
|
|
# Required for deterministic artifact URL resolution.
|
|
"public_url_base": os.environ.get("LIVEKIT_RECORDING_PUBLIC_URL_BASE", ""),
|
|
# Optional. Include upload credentials only if the plugin should write
|
|
# directly to S3 instead of relying on LiveKit project defaults.
|
|
"access_key": os.environ.get("LIVEKIT_RECORDING_S3_ACCESS_KEY", ""),
|
|
"secret": os.environ.get("LIVEKIT_RECORDING_S3_SECRET", ""),
|
|
"region": os.environ.get("LIVEKIT_RECORDING_S3_REGION", ""),
|
|
"bucket": os.environ.get("LIVEKIT_RECORDING_S3_BUCKET", ""),
|
|
},
|
|
},
|
|
)
|
|
```
|
|
|
|
### Managed Room Composite
|
|
|
|
```python
|
|
hamming.configure_hamming(
|
|
api_key=os.environ["HAMMING_API_KEY"],
|
|
external_agent_id=os.environ["HAMMING_EXTERNAL_AGENT_ID"],
|
|
recording={
|
|
"mode": "room_composite",
|
|
"livekit": {
|
|
"url": os.environ["LIVEKIT_URL"],
|
|
"api_key": os.environ["LIVEKIT_API_KEY"],
|
|
"api_secret": os.environ["LIVEKIT_API_SECRET"],
|
|
},
|
|
"audio_only": True,
|
|
"file_type": "ogg",
|
|
},
|
|
)
|
|
```
|
|
|
|
Notes:
|
|
|
|
- Managed remote recording modes require LiveKit server API credentials.
|
|
- Managed remote recording modes also require `job_ctx` when calling `hamming.attach_session(...)`.
|
|
- Managed remote recording modes require deterministic artifact URL resolution via `recording.s3.public_url_base` or `recording.s3.bucket` + `recording.s3.region`.
|
|
- If you provide full S3 credentials, the plugin uses those upload settings for egress output.
|
|
- If you omit S3 upload credentials, your LiveKit project must already have default file output storage configured.
|
|
- The plugin does not poll LiveKit for completed artifact locations; it derives the final public URLs from the configured output path.
|
|
|
|
## Verify configuration
|
|
|
|
```python
|
|
import os
|
|
|
|
from livekit.plugins import hamming
|
|
|
|
report = hamming.doctor(api_key=os.environ["HAMMING_API_KEY"])
|
|
print(report.to_dict())
|
|
```
|
|
|
|
## Notes
|
|
|
|
- Sessions are exported when attached through `hamming.attach_session(...)`.
|
|
- Recording is opt-in. Omitting `recording=...` sends monitoring payloads without recording artifacts.
|
|
- `auto_record_audio=True` is still supported as a backward-compatible alias for `recording={"mode": "session_audio"}`.
|
|
- Managed remote recording modes stop egress on close and send deterministic artifact URLs through the same `/api/rest/v2/collect` ingestion path.
|
|
|
|
## Troubleshooting
|
|
|
|
- `RuntimeError: hamming is not configured`
|
|
- Call `hamming.configure_hamming(...)` before `hamming.attach_session(...)`.
|
|
- `ValueError: Hamming API key required`
|
|
- Set `HAMMING_API_KEY` or pass `api_key=...`.
|
|
- `external_agent_id is required`
|
|
- Set `HAMMING_EXTERNAL_AGENT_ID` or pass `external_agent_id=...`.
|
|
- `Unsupported recording mode`
|
|
- Use `none`, `session_audio`, `participant_egress`, or `room_composite`.
|
|
- `recording mode 'participant_egress' requires LiveKit server credentials`
|
|
- Provide `recording.livekit` or set `LIVEKIT_URL`, `LIVEKIT_API_KEY`, and `LIVEKIT_API_SECRET`.
|
|
- `recording mode 'participant_egress' requires deterministic artifact URL resolution`
|
|
- Provide `recording.s3.public_url_base` or `recording.s3.bucket` + `recording.s3.region`.
|
|
- `recording mode 'participant_egress' requires JobContext`
|
|
- Pass `job_ctx=ctx` to `hamming.attach_session(...)` or call it from inside the active LiveKit job.
|