Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.phrony.com/llms.txt

Use this file to discover all available pages before exploring further.

This walkthrough goes from zero to a working API integration: you configure an agent in the Phrony dashboard, then drive it from your backend with X-API-Key. It also covers human-in-the-loop (HITL)—pausing for approval or input—and how to respond to user tasks with the same API instead of only in the dashboard. You should already have a workspace, an LLM provider, and permissions to create agents and API keys.

What you will set up

In the Phrony dashboardIn your code
Agent, deployed version, API trigger, API key scoped to that agent + triggerPOST to start a run, GET to poll, optional GET conversation
Optional: HITL execution mode and an integration operation with Require approval (HITL)When the run waits, GET conversation to read user_task_id, then POST to resume with userTaskId + approved (or other fields)
Full endpoint details: API Reference — especially Agents and Runs. For TypeScript, you can also use the official TypeScript SDK (@phrony/sdk) so you do not hand-author every fetch call.

Part 1 — Create the agent and API access in the dashboard

1. Create or open an agent

In the Phrony dashboard, open your workspace and go to Agents. Create an agent or pick an existing one. Give it a clear name; you will reference it by id in code.

2. Configure a version you can deploy

Open the Versions (or Editor) area for that agent and add a version:
  • Choose a model and prompt appropriate to your use case.
  • Under Integrations / operations, attach at least one tool the model can call. For a HITL demo, edit an operation and turn on Require approval (HITL) before execution (or the equivalent for that connector) so runs can pause until someone approves the call.
  • Set execution mode to HITL if you want people in the loop on the main path (recommended for approval flows).
Save the version when you are ready.

3. Deploy a version

Deploy the version so the platform has a fixed snapshot to run. API runs always use what is deployed, not a draft.

4. Add an API trigger

Open Triggers on the agent and add a trigger of type API.
  • Note the trigger id (you will need it when scoping an API key).
  • For HITL + API, set Expose step timeline to API clients to on. If this is off, external GET .../conversation and .../stream calls are redacted and you may not see user task steps or ids—so you cannot complete tasks from your integration. See Embedded agents — API redaction.
Optional: configure rate limits, IP allowlists, or concurrency on the trigger to match your environment.

5. Create an API key

Go to Settings (workspace) → API keys (or your workspace’s API key page).
  • Create a key and copy the secret (prefix phk_). Store it in a secret manager or environment variable—never expose it in a browser or mobile app.
  • Add a scope that includes this agent and this API trigger only.
  • If you will use file uploads, enable Allow file uploads for the key.
On the agent’s API trigger screen, the Access tab shows the public base URL (for Phrony Cloud: https://api.phrony.com) and your agentId—match those in your code.

Part 2 — Start a run and read the result from code

Set environment variables (names are suggestions):
VariableValue
PHRONY_API_BASEhttps://api.phrony.com (or your team’s base URL)
PHRONY_API_KEYYour phk_... key
AGENT_IDThe agent UUID from the dashboard
1. Start a run with POST /v1/agents/{agentId}/runs and a JSON body shaped to your agent’s input contract, for example:
{ "input": { "query": "Hello from the API" } }
2. Read sessionId and runId from the 202 response. 3. Poll GET /v1/runs/{runId} until the run reaches a terminal state or a state that means “waiting for a person” (see Part 3). Use the same X-API-Key on every call.
curl -sS -X POST "${PHRONY_API_BASE}/v1/agents/${AGENT_ID}/runs" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: ${PHRONY_API_KEY}" \
  -d '{"input":{"query":"Hello"}}'

Part 3 — HITL: discover a user task and respond with the API

When the model hits an operation that requires approval, the run pauses and Phrony creates a user task. Your backend can treat this like a second phase of the same runId:
  1. Poll GET /v1/runs/{runId} until status indicates the run is waiting for input—common values include WaitingForHITL, WaitingForAITL, and WaitingForResponse (your workspace may use the same strings in the public poll body). If the run finishes without a pause, there is no task to complete in that loop.
  2. Fetch the timeline with GET /v1/runs/{runId}/conversation (same API key). With Expose step timeline to API clients on, the JSON includes an items array. Find the row whose type is UserTaskReq: the step content includes a user_task_id (snake_case in the payload) identifying the pending task.
  3. Resume with POST /v1/runs/{runId}/messages (or .../input) and a JSON body that includes:
    • runId — same UUID as in the path
    • userTaskId — the value from content.user_task_id
    • approvedtrue to approve the tool call, false to reject (when the task is an approval-style HITL step)
Other user task kinds use different fields (for example selectedOptionId, textValue, numberValue). See Runs — Send input or messages.
  1. Poll GET /v1/runs/{runId} again. The run may continue, pause again (another task), or complete.
Waiting for chat-style text: If the run is WaitingForResponse, send text or message instead of userTaskId (see the same API reference section). Example (TypeScript SDK) after you have runId and have called getConversation:
import { Phrony, type ConversationResponse, PhronyAPIError } from "@phrony/sdk";

const phrony = new Phrony({
  apiKey: process.env.PHRONY_API_KEY!,
  baseUrl: process.env.PHRONY_API_BASE ?? "https://api.phrony.com",
});

function findPendingUserTaskId(conv: ConversationResponse): string | null {
  for (const it of conv.items) {
    if (it.type !== "UserTaskReq" || it.content == null || typeof it.content !== "object") {
      continue;
    }
    const id = (it.content as { user_task_id?: string }).user_task_id;
    if (typeof id === "string") {
      return id;
    }
  }
  return null;
}

async function approveOrReject(runId: string, userTaskId: string, approved: boolean) {
  try {
    return await phrony.sendRunMessage(runId, { userTaskId, approved });
  } catch (e) {
    if (e instanceof PhronyAPIError) {
      throw new Error(`messages: ${e.status} ${e.body}`);
    }
    throw e;
  }
}
Use GET /v1/runs/{runId}/stream (SSE) if you prefer event-driven waiting instead of polling; the same Expose step timeline setting applies. See Runs — Stream (SSE) for the event shape.

Checklist

  • Version deployed; API trigger created; API key scoped to that agent + trigger
  • HITL demo: HITL mode + at least one operation with Require approval, if you want approval tasks
  • For HITL over HTTP: Expose step timeline to API clients = on on the API trigger
  • Your service stores phk_ securely and only calls the API from your backend
  • You handle both WaitingForHITL-style and terminal run outcomes in a loop