mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-06-07 07:55:16 +02:00
chore: updatae documentation for api trigger
This commit is contained in:
parent
5ad5bbd985
commit
0d7b225f76
12 changed files with 120 additions and 39 deletions
|
|
@ -14,7 +14,10 @@ from pydantic import BaseModel
|
|||
from api.db import db_client
|
||||
from api.enums import TriggerState
|
||||
from api.services.quota_service import check_dograh_quota_by_user_id
|
||||
from api.services.telephony.factory import get_default_telephony_provider
|
||||
from api.services.telephony.factory import (
|
||||
get_default_telephony_provider,
|
||||
get_telephony_provider_by_id,
|
||||
)
|
||||
from api.utils.common import get_backend_endpoints
|
||||
|
||||
router = APIRouter(prefix="/public/agent")
|
||||
|
|
@ -25,6 +28,7 @@ class TriggerCallRequest(BaseModel):
|
|||
|
||||
phone_number: str
|
||||
initial_context: Optional[dict] = None
|
||||
telephony_configuration_id: int | None = None
|
||||
|
||||
|
||||
class TriggerCallResponse(BaseModel):
|
||||
|
|
@ -114,14 +118,38 @@ async def _initiate_call(
|
|||
detail="Trigger not found in the published Agent",
|
||||
)
|
||||
|
||||
# 6. Get telephony provider for the organization (using its default config).
|
||||
try:
|
||||
provider = await get_default_telephony_provider(trigger.organization_id)
|
||||
except ValueError:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="Telephony provider not configured for this organization",
|
||||
# 6. Get telephony provider — either the caller-specified config (validated
|
||||
# against the trigger's org) or the org's default config.
|
||||
if request.telephony_configuration_id is not None:
|
||||
cfg = await db_client.get_telephony_configuration_for_org(
|
||||
request.telephony_configuration_id, trigger.organization_id
|
||||
)
|
||||
if not cfg:
|
||||
raise HTTPException(
|
||||
status_code=404, detail="Telephony configuration not found"
|
||||
)
|
||||
try:
|
||||
provider = await get_telephony_provider_by_id(
|
||||
cfg.id, trigger.organization_id
|
||||
)
|
||||
except ValueError:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="Telephony provider not configured for this configuration",
|
||||
)
|
||||
resolved_cfg_id = cfg.id
|
||||
else:
|
||||
try:
|
||||
provider = await get_default_telephony_provider(trigger.organization_id)
|
||||
except ValueError:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="Telephony provider not configured for this organization",
|
||||
)
|
||||
default_cfg = await db_client.get_default_telephony_configuration(
|
||||
trigger.organization_id
|
||||
)
|
||||
resolved_cfg_id = default_cfg.id if default_cfg else None
|
||||
|
||||
# Validate provider is configured
|
||||
if not provider.validate_config():
|
||||
|
|
@ -130,10 +158,6 @@ async def _initiate_call(
|
|||
detail="Telephony provider not configured for this organization",
|
||||
)
|
||||
|
||||
default_cfg = await db_client.get_default_telephony_configuration(
|
||||
trigger.organization_id
|
||||
)
|
||||
|
||||
# 7. Determine the workflow run mode based on provider type
|
||||
workflow_run_mode = provider.PROVIDER_NAME
|
||||
|
||||
|
|
@ -149,7 +173,7 @@ async def _initiate_call(
|
|||
"phone_number": request.phone_number,
|
||||
"agent_uuid": uuid,
|
||||
"trigger_mode": "test" if use_draft else "production",
|
||||
"telephony_configuration_id": default_cfg.id if default_cfg else None,
|
||||
"telephony_configuration_id": resolved_cfg_id,
|
||||
**(request.initial_context or {}),
|
||||
},
|
||||
user_id=api_key.created_by,
|
||||
|
|
|
|||
|
|
@ -27,11 +27,6 @@ from pipecat.pipeline.pipeline import Pipeline
|
|||
from pipecat.processors.aggregators.llm_response_universal import (
|
||||
LLMContextAggregatorPair,
|
||||
)
|
||||
from pipecat.processors.filters.stt_mute_filter import (
|
||||
STTMuteConfig,
|
||||
STTMuteFilter,
|
||||
STTMuteStrategy,
|
||||
)
|
||||
|
||||
|
||||
class LoopTalkPipelineBuilder:
|
||||
|
|
@ -126,13 +121,6 @@ class LoopTalkPipelineBuilder:
|
|||
|
||||
context_aggregator = LLMContextAggregatorPair(context)
|
||||
|
||||
# Create STT mute filter
|
||||
stt_mute_filter = STTMuteFilter(
|
||||
config=STTMuteConfig(
|
||||
strategies={STTMuteStrategy.FIRST_SPEECH},
|
||||
)
|
||||
)
|
||||
|
||||
# Create pipeline engine callback processor
|
||||
pipeline_engine_callback_processor = PipelineEngineCallbacksProcessor(
|
||||
max_call_duration_seconds=300,
|
||||
|
|
@ -152,7 +140,6 @@ class LoopTalkPipelineBuilder:
|
|||
[
|
||||
transport.input(),
|
||||
audio_streamer, # Stream audio to connected clients
|
||||
stt_mute_filter,
|
||||
stt,
|
||||
transcript.user(),
|
||||
user_context_aggregator,
|
||||
|
|
|
|||
|
|
@ -22,7 +22,15 @@ SPEC = NodeSpec(
|
|||
" • Test: `<backend>/api/v1/public/agent/test/<trigger_path>` — runs "
|
||||
"the latest draft, useful for verifying changes before publishing. "
|
||||
"Falls back to the published agent when no draft exists.\n"
|
||||
"Both require an API key in the `X-API-Key` header."
|
||||
"Both require an API key in the `X-API-Key` header.\n"
|
||||
"Request body fields:\n"
|
||||
" • `phone_number` (string, required) — destination to dial.\n"
|
||||
" • `initial_context` (object, optional) — merged into the run's "
|
||||
"initial context.\n"
|
||||
" • `telephony_configuration_id` (int, optional) — pick a specific "
|
||||
"telephony configuration for the call. Must belong to the same "
|
||||
"organization as the trigger. When omitted, the org's default "
|
||||
"outbound configuration is used."
|
||||
),
|
||||
category=NodeCategory.trigger,
|
||||
icon="Webhook",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ description: "Initiate outbound calls and trigger agents via the API"
|
|||
| Method | Endpoint | Quick Link |
|
||||
|---|---|---|
|
||||
| `POST` | `/public/agent/{uuid}` | [Trigger an outbound call](/api-reference/calls/trigger) |
|
||||
| `POST` | `/telephony/initiate-call` | [Initiate a call (authenticated)](/api-reference/calls/initiate) |
|
||||
| `GET` | `/workflow/{workflow_id}/runs/{run_id}` | [Retrieve call details](/api-reference/calls/get-run) |
|
||||
| `GET` | `/public/download/workflow/{token}/{artifact_type}` | [Download recordings and transcripts](/api-reference/calls/download) |
|
||||
| `POST` | `/telephony/inbound/{workflow_id}` | [Inbound call webhook](/api-reference/calls/inbound) |
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
---
|
||||
title: "Initiate a Call (Authenticated)"
|
||||
description: "Start an outbound call with more control than the public endpoint"
|
||||
openapi: "POST /api/v1/telephony/initiate-call"
|
||||
---
|
||||
|
||||
Use this endpoint when you need to specify a `workflow_run_id` to resume context from a previous run, or when you want to use the workflow's integer ID instead of its public UUID.
|
||||
|
|
@ -4,12 +4,14 @@ description: "Initiate an outbound call using an agent's public UUID"
|
|||
openapi: "POST /api/v1/public/agent/{uuid}"
|
||||
---
|
||||
|
||||
The simplest way to initiate a call programmatically. The `uuid` is visible in the dashboard URL when viewing an agent.
|
||||
The simplest way to initiate a call programmatically. The `uuid` comes from the [API Trigger node](/voice-agent/api-trigger) in your agent — add the node to your workflow and copy its auto-generated `trigger_path`.
|
||||
|
||||
Use `workflow_run_id` from the response to later [retrieve call details](/api-reference/calls/get-run), recordings, and transcripts.
|
||||
|
||||
Pass `initial_context` to inject runtime data as template variables into the agent's prompt. See [Using initial context](/api-reference/calls#using-initial-context).
|
||||
|
||||
Pass `telephony_configuration_id` to route the call through a specific telephony configuration instead of your organization's default. The id is shown on each row in **Telephony configurations** (`https://app.dograh.com/telephony-configurations` for hosted or `http://localhost:3010/telephony-configurations` for local).
|
||||
|
||||
<Note>
|
||||
Your telephony provider must be configured before outbound calls will connect. See [Telephony](/integrations/telephony/overview) for setup instructions.
|
||||
</Note>
|
||||
|
|
|
|||
|
|
@ -202,7 +202,6 @@
|
|||
"pages": [
|
||||
"api-reference/calls",
|
||||
"api-reference/calls/trigger",
|
||||
"api-reference/calls/initiate",
|
||||
"api-reference/calls/get-run",
|
||||
"api-reference/calls/download",
|
||||
"api-reference/calls/inbound"
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ The request body, headers, and response shape are identical for both URLs.
|
|||
|
||||
## Making a request
|
||||
|
||||
Authenticate by passing your API key in the `X-API-Key` header. The request body requires a `phone_number` and accepts an optional `initial_context` object.
|
||||
Authenticate by passing your API key in the `X-API-Key` header. The request body requires a `phone_number` and accepts optional `initial_context` and `telephony_configuration_id` fields.
|
||||
|
||||
```bash
|
||||
curl -X POST https://your-dograh-instance/api/v1/public/agent/{uuid} \
|
||||
|
|
@ -92,6 +92,19 @@ You can reference the user's name in your prompt as `{{initial_context.user.name
|
|||
|
||||
See [Context & Variables](/core-concepts/context-and-variables) for more on how data flows through a call.
|
||||
|
||||
## Choosing a telephony configuration
|
||||
|
||||
By default, calls are placed through your organization's default outbound [telephony configuration](/integrations/telephony/overview). To route a specific call through a different configuration — for example, to dial out from a regional number — pass `telephony_configuration_id` in the request body.
|
||||
|
||||
```json
|
||||
{
|
||||
"phone_number": "+14155550100",
|
||||
"telephony_configuration_id": 42
|
||||
}
|
||||
```
|
||||
|
||||
The id is shown on each row in **Telephony configurations** (`https://app.dograh.com/telephony-configurations` for hosted or `http://localhost:3010/telephony-configurations` for local). The configuration must belong to the same organization as the API Trigger; otherwise the request returns `404`.
|
||||
|
||||
<Note>
|
||||
For full endpoint details including all parameters and response fields, see the [API reference](/api-reference/calls/trigger).
|
||||
</Note>
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import {
|
||||
ArrowLeft,
|
||||
Copy,
|
||||
ExternalLink,
|
||||
Pencil,
|
||||
Plus,
|
||||
|
|
@ -212,6 +213,20 @@ export default function TelephonyConfigurationDetailPage() {
|
|||
<CardDescription>
|
||||
Updated {new Date(config.updated_at).toLocaleString()}
|
||||
</CardDescription>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
navigator.clipboard
|
||||
.writeText(String(config.id))
|
||||
.then(() => toast.success("Configuration ID copied"))
|
||||
.catch(() => toast.error("Failed to copy ID"));
|
||||
}}
|
||||
title="Click to copy"
|
||||
className="inline-flex items-center gap-1 self-start rounded font-mono text-xs text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<span className="truncate">Configuration ID: {config.id}</span>
|
||||
<Copy className="h-3 w-3 shrink-0" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 shrink-0">
|
||||
{!config.is_default_outbound && (
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import {
|
||||
ChevronRight,
|
||||
Copy,
|
||||
ExternalLink,
|
||||
Pencil,
|
||||
Plus,
|
||||
|
|
@ -198,6 +199,22 @@ export default function TelephonyConfigurationsPage() {
|
|||
{item.phone_number_count} phone{" "}
|
||||
{item.phone_number_count === 1 ? "number" : "numbers"}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
navigator.clipboard
|
||||
.writeText(String(item.id))
|
||||
.then(() => toast.success("Configuration ID copied"))
|
||||
.catch(() => toast.error("Failed to copy ID"));
|
||||
}}
|
||||
title="Click to copy"
|
||||
className="inline-flex items-center gap-1 self-start rounded font-mono text-xs text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<span className="truncate">Configuration ID: {item.id}</span>
|
||||
<Copy className="h-3 w-3 shrink-0" />
|
||||
</button>
|
||||
</div>
|
||||
</Link>
|
||||
<div className="flex items-center gap-1">
|
||||
|
|
|
|||
|
|
@ -3714,6 +3714,10 @@ export type TriggerCallRequest = {
|
|||
initial_context?: {
|
||||
[key: string]: unknown;
|
||||
} | null;
|
||||
/**
|
||||
* Telephony Configuration Id
|
||||
*/
|
||||
telephony_configuration_id?: number | null;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use client";
|
||||
|
||||
import { ExternalLink } from "lucide-react";
|
||||
import { Copy, ExternalLink } from "lucide-react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
|
|
@ -172,6 +172,26 @@ export function ConfigFormDialog({
|
|||
</DialogHeader>
|
||||
|
||||
<div className="space-y-4">
|
||||
{isEdit && existing && (
|
||||
<div className="space-y-1">
|
||||
<Label>Configuration ID</Label>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
navigator.clipboard
|
||||
.writeText(String(existing.id))
|
||||
.then(() => toast.success("Configuration ID copied"))
|
||||
.catch(() => toast.error("Failed to copy ID"));
|
||||
}}
|
||||
title="Click to copy"
|
||||
className="group flex w-full items-center gap-2 rounded-md border bg-muted/20 p-2 text-left font-mono text-xs transition-colors hover:bg-muted/40"
|
||||
>
|
||||
<code className="flex-1 truncate">{existing.id}</code>
|
||||
<Copy className="h-3 w-3 shrink-0 text-muted-foreground group-hover:text-foreground" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="cfg-name">Name</Label>
|
||||
<Input
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue