> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt.

# 구조화된 절차

## 개요

구조화된 절차는 고정된 순서의 단계를 실행하는 [절차](/docs/ko/eleven-agents/customization/procedures)입니다. [자유 형식 절차](/docs/ko/eleven-agents/customization/procedures/free-form-procedures)는 에이전트가 해석하고 상황에 맞게 조정하는 자연어 지침입니다. 구조화된 절차는 절차가 적용될 때마다 에이전트가 순서대로 실행하는, 유형이 지정된 단계의 정렬된 목록입니다.

발신자 신원 확인, 티켓 에스컬레이션, 결제 처리처럼 모든 통화에서 특정 단계를 동일한 방식으로 수행해야 할 때 구조화된 절차를 사용하세요. 일반 언어로 된 짧은 단계 목록으로 작성할 수 있습니다.

모든 절차와 마찬가지로 구조화된 절차에는 적용 시점을 설명하는 트리거가 있습니다. 대화가 트리거와 일치하면 에이전트는 절차 단계를 순서대로 실행한 후 나머지 대화로 돌아갑니다.

![구조화된 절차
편집기](/docs/_fern-files/_img/bc996f67b2afad8f1de5abe8febcf8af3766b4f098627b0ae60e0456b3c2703b.webp)

## 구조화된 절차를 사용해야 하는 경우

특정 단계를 매번 동일하게 실행해야 하지만 일반 단계로 빠르게 작성하고 싶을 때 구조화된 절차를 사용하세요. 구조화된 절차는 워크플로보다 작성하기 쉽지만 표현력은 낮습니다. 자유 형식 절차, 워크플로 및 시스템 프롬프트와의 비교는 [절차 사용 시점](/docs/ko/eleven-agents/customization/procedures#when-to-use-procedures)을 참조하세요.

## 구조화된 절차의 구성 요소

구조화된 절차는 이름, 트리거, 정렬된 단계 목록의 세 부분으로 구성됩니다.

### 이름

대시보드에서 절차를 식별하는 짧은 라벨입니다. 이름은 LLM에 전송되지 않으므로 에이전트 동작에 영향을 주지 않습니다.

### 트리거

에이전트가 이 절차를 실행해야 하는 시점에 대한 일반 언어 설명입니다. 예: *사용자가 주문 환불을 요청할 때*. 에이전트는 사용자 의도를 각 절차의 트리거와 비교하여 일치하는 절차를 실행하므로, 트리거는 구체적이고 서로 구분되어야 합니다. 에이전트는 절차의 이름이나 ID가 아닌 트리거 텍스트만 봅니다. 트리거는 모든 절차에서 동일하게 작동합니다. 자세한 내용은 [트리거 작성](/docs/ko/eleven-agents/customization/procedures/free-form-procedures#writing-triggers)을 참조하세요.

트리거를 비워 두면 다른 절차가 호출할 때만 실행되는 하위 절차가 됩니다.

### 단계

절차 본문은 유형이 지정된 단계의 정렬된 목록입니다. 여러 단계 유형이 있으며, 이를 조합해 작업을 설명합니다.

| 단계                | 기능                                                                                                                    |
| ----------------- | --------------------------------------------------------------------------------------------------------------------- |
| **Ask**           | 사용자에게 정보를 요청하고 기다립니다. 사용자가 답할 때까지 계속 질문합니다. 사용자를 위해 일시 중지되는 유일한 단계입니다.                                                |
| **Tell**          | 에이전트가 자체 표현으로 내용을 전달한 후 다음 단계로 넘어갑니다.                                                                                 |
| **Say**           | 에이전트가 정확한 메시지를 한 글자도 바꾸지 않고 말한 후 다음 단계로 넘어갑니다. Say 단계는 에이전트가 지원하는 각 언어에 대해 별도로 구성된 번역을 포함할 수 있습니다.                    |
| **Tool**          | 특정 도구를 호출합니다. LLM에 도구 호출 방법을 일반 언어로 지시하거나, 최대한의 결정성이 필요할 때 매개변수 값을 명시적으로 고정할 수 있습니다. 도구 호출이 실패할 때 실행할 단계도 정의할 수 있습니다. |
| **If**            | 하나 이상의 조건을 순서대로 평가하고 첫 번째로 일치하는 항목의 단계를 실행합니다. 일치하는 항목이 없을 때 선택적 Else가 실행됩니다.                                         |
| **Sub-procedure** | 다른 구조화된 절차를 실행합니다. 해당 단계가 완료되면 이(호출자) 절차의 다음 단계로 제어가 돌아옵니다.                                                           |
| **System tool**   | 내장 시스템 작업을 수행합니다. 현재는 통화 종료만 지원됩니다.                                                                                   |
| **Retry**         | 도구 호출을 포함하여 Tool 단계의 실패 핸들러를 최대 3회 다시 실행합니다. Tool 단계의 실패 핸들러 내부에서만 사용할 수 있습니다.                                        |

![구조화된 절차 단계 유형
메뉴](/docs/_fern-files/_img/14976a6b9979d21fd7c77541a49e7475f8aa0764af4940746d3390804e7c4598.webp)

모든 단계가 어디서나 나타날 수 있는 것은 아닙니다. If 분기 내부에서는 다른 If 또는 Retry를 제외한 모든 단계를 사용할 수 있습니다. Tool 단계의 실패 핸들러 내부에서는 If 또는 다른 Tool을 제외한 모든 단계를 사용할 수 있습니다.

## API 단계 레퍼런스

구조화된 절차의 `content`는 `steps` 배열을 포함하는 JSON 인코딩 문서입니다. 각 단계는 `type`으로 식별되는 객체입니다. 트리거는 `content`의 일부가 아니라 절차의 별도 최상위 필드입니다. API 및 SDK 페이로드에서는 절차 자체에 `type: "deterministic"`를 사용합니다.

### Ask

Ask 단계는 에이전트에게 정보를 요청하고 사용자가 적절한 응답을 제공할 때까지 기다리도록 지시합니다.

* API 유형: `ask`
* `instruction`: 필수, 비어 있지 않은 문자열.

```json focus={1-4}
{
  "type": "ask",
  "instruction": "Ask the user for their order ID."
}
```

### Tell

Tell 단계는 에이전트가 자체 표현으로 하나의 메시지를 생성하도록 지시합니다. 계속 진행하기 전에 사용자 응답을 기다리지 않습니다.

* API 유형: `tell`
* `instruction`: 필수, 비어 있지 않은 문자열.

```json focus={1-4}
{
  "type": "tell",
  "instruction": "Explain that the refund normally takes five to ten business days."
}
```

### Say

Say 단계는 제공된 텍스트를 작성된 그대로 말한 후 계속 진행합니다. 에이전트가 지원하는 각 추가 언어에 대한 정확한 메시지를 언어 코드별로 제공하려면 `message_translations`를 사용하세요.

* API 유형: `say`
* `message`: 필수, 비어 있지 않은 문자열.
* `message_translations`: 언어 코드를 `{ "value": "..." }`에 매핑하는 선택적 객체.

```json focus={1-7}
{
  "type": "say",
  "message": "Your refund has been submitted.",
  "message_translations": {
    "es": { "value": "Su reembolso ha sido enviado." }
  }
}
```

### If, else if, else

If 단계에는 순서가 있는 하나 이상의 조건 분기가 포함됩니다. 처음으로 일치하는 분기가 실행됩니다. 선택적 `fallback` 배열은 Else 분기입니다.

* API 유형: `branch`
* `branches`: 필수, 비어 있지 않은 조건 분기 목록.
* `fallback`: 선택적 Else 단계 목록.
* 각 분기에는 `condition` 및 비어 있지 않은 `steps` 목록이 필요합니다.

```json focus={1-23}
{
  "type": "branch",
  "branches": [
    {
      "condition": {
        "type": "llm",
        "condition": "The user is on an annual plan."
      },
      "steps": [
        {
          "type": "say",
          "message": "Your annual plan is eligible for a prorated refund."
        }
      ]
    }
  ],
  "fallback": [
    {
      "type": "tell",
      "instruction": "Explain that the account's plan could not be determined."
    }
  ]
}
```

다음과 같이 if/else-if/else로 동작합니다.

1. 조건을 순서대로 평가합니다.
2. 처음으로 일치하는 분기를 실행합니다.
3. 일치하는 조건이 없으면 `fallback`을 실행합니다.
4. 분기가 완료되면 절차는 기본 시퀀스로 다시 합류합니다.

위 예제는 모델이 자연어로 평가하는 텍스트 조건을 사용합니다. 조건은 동적 변수에 대한 표현식일 수도 있습니다.

```json focus={1-14}
{
  "type": "expression",
  "expression": {
    "type": "eq_operator",
    "left": {
      "type": "dynamic_variable",
      "name": "plan_tier"
    },
    "right": {
      "type": "string_literal",
      "value": "annual"
    }
  }
}
```

표현식 조건은 도구 결과로 채워지거나 대화 시작 시 설정되는 동적 변수를 검사합니다. 사용자의 가장 최근 답변은 읽을 수 없습니다. 사용자가 말한 내용에 따라 분기하려면 텍스트 조건을 사용하세요.

하나의 If 단계에 있는 모든 분기는 `llm` 또는 `expression` 중 하나로 동일한 조건 유형을 사용해야 합니다.

### Tool

Tool 단계는 특정 도구를 호출합니다.

* API 유형: `tool_call`
* `tool_id`: 필수, 비어 있지 않은 도구 ID입니다. 도구가 에이전트에 연결되어 있어야 합니다.
* `tool_name`: 도구와 일치하는 필수 도구 이름입니다.
* `instruction`: 도구 호출 방법을 설명하는 선택적 지침입니다.
* `schema_overrides`: 도구 매개변수의 선택적 고정값입니다.
* `on_failure`: 선택적 실패 핸들러입니다.

```json focus={1-6}
{
  "type": "tool_call",
  "tool_id": "tool_abc123",
  "tool_name": "lookup_order",
  "instruction": "Look up the order using the order ID provided by the user."
}
```

#### 고정 매개변수 값

매개변수가 항상 특정 값을 가져야 하는 경우 `schema_overrides`를 사용하세요. 모델은 재정의된 매개변수를 보거나 선택하지 않습니다. 키는 도구 스키마의 매개변수 경로이며, 각 값은 소스를 지정합니다.

| `source`           | 필드                 | 동작                                        |
| ------------------ | ------------------ | ----------------------------------------- |
| `constant`         | `constant_value`   | 지정된 값을 항상 전송합니다.                          |
| `dynamic_variable` | `dynamic_variable` | 이름이 지정된 동적 변수의 현재 값을 전송합니다.               |
| `llm`              | `prompt` (선택 사항)   | 모델이 값을 선택하도록 하며, 선택적으로 프롬프트를 재정의할 수 있습니다. |
| `omit`             |                    | 호출에서 매개변수를 제외합니다.                         |

```json focus={1-9}
{
  "type": "tool_call",
  "tool_id": "tool_abc123",
  "tool_name": "update_ticket",
  "schema_overrides": {
    "request_body.status": { "source": "constant", "constant_value": "pending" },
    "request_body.ticket_id": { "source": "dynamic_variable", "dynamic_variable": "ticket_id" }
  }
}
```

#### 실패 처리

`on_failure`가 없으면 도구 호출 실패 시 대화가 종료됩니다. 대신 복구 단계를 실행하려면 `on_failure`를 추가하세요.

* `fallback`: 필수, 도구 실패 시 실행되는 비어 있지 않은 단계 목록.
* `branches`: 조건부 실패 처리를 위해 예약되어 있습니다. 비워 두세요.

```json focus={1-14}
{
  "type": "tool_call",
  "tool_id": "tool_abc123",
  "tool_name": "lookup_order",
  "on_failure": {
    "branches": [],
    "fallback": [
      {
        "type": "tell",
        "instruction": "Explain that the order could not be retrieved and offer to connect the user with support."
      }
    ]
  }
}
```

실패 핸들러에는 Ask, Tell, Say, Sub-procedure, System tool, Retry 단계가 포함될 수 있습니다. Tool 또는 If 단계는 포함할 수 없습니다. 핸들러가 실행된 후 절차는 Tool 단계 다음 단계로 계속 진행됩니다.

### Retry

Retry 단계는 도구 호출을 포함하여 이를 포함하는 실패 핸들러를 다시 실행합니다. 각 시도는 도구를 다시 호출하며, 다시 실패하면 핸들러의 모든 단계를 다시 실행합니다. 시도를 모두 사용하면 대화가 종료됩니다.

* API 유형: `retry`
* `max_retries`: 1에서 3까지의 선택적 정수입니다. 기본값은 1입니다.
* 값은 원래 도구 호출 이후의 시도 횟수를 계산합니다.
* Retry는 `on_failure` 내부에서만 유효합니다.
* 이후 단계에 도달할 수 없으므로 Retry는 실패 핸들러의 마지막 단계여야 합니다.

```json focus={1-4}
{
  "type": "retry",
  "max_retries": 2
}
```

### Sub-procedure

Sub-procedure 단계는 다른 구조화된 절차를 실행합니다. 해당 절차의 단계가 완료되면 실행은 Sub-procedure 단계 다음 단계로 돌아갑니다.

* API 유형: `sub_procedure`
* `procedure_id`: 필수, 비어 있지 않은 절차 ID.
* 대상은 동일한 에이전트에 존재해야 합니다.
* 대상은 구조화된 절차여야 합니다.
* 절차는 자신을 호출할 수 없습니다.

```json focus={1-4}
{
  "type": "sub_procedure",
  "procedure_id": "agtprc_6qbpwdq8n01bxhk44bgjy6f10ck3"
}
```

### System tool

System tool 단계는 내장 시스템 작업을 수행합니다.

* API 유형: `system_tool`
* `system_tool_name`: 필수 시스템 도구 이름.
* 현재는 `end_call`만 지원됩니다. 이후 더 많은 시스템 도구가 추가될 수 있습니다.
* `end_call`은 종료 작업이므로 포함된 시퀀스, 분기 또는 실패 핸들러의 마지막 단계여야 합니다.

```json focus={1-4}
{
  "type": "system_tool",
  "system_tool_name": "end_call"
}
```

## 검증 규칙

에이전트를 게시하거나 에이전트 초안을 저장하면, 다음 규칙 중 하나라도 위반하는 구조화된 절차는 거부됩니다. 오류는 경로를 통해 문제가 있는 단계를 표시합니다.

* 두 If 단계를 연속해서 배치할 수 없습니다.
* If 단계는 중첩할 수 없습니다.
* 표현식 조건이 있는 If 단계는 Ask 단계 바로 다음에 올 수 없습니다.
* 하나의 If 단계에 있는 모든 조건은 `llm` 또는 `expression` 중 하나로 동일한 유형이어야 합니다.
* Retry는 `on_failure` 내부에만 나타날 수 있으며, 그 안에서 마지막 단계여야 합니다.
* `end_call`은 포함된 모든 목록에서 마지막 단계여야 합니다.
* 실패 핸들러의 `fallback`에는 최소 하나의 단계가 포함되어야 합니다.
* Sub-procedure는 동일한 에이전트에 있는 기존 구조화된 절차를 가리켜야 하며, 자기 자신을 가리킬 수 없습니다.
* `tool_id`는 에이전트의 도구여야 하고, `tool_name`은 일치해야 하며, `schema_overrides`는 도구의 스키마와 일치해야 합니다.
* `steps` 목록과 모든 `instruction`, 모든 `message`는 비어 있지 않아야 합니다.

이러한 규칙 중 하나에 해당하는 절차를 재구성하는 방법은 [모범 사례](#best-practices)를 참조하세요.

## 전체 API 예제

이 예제는 배송 상태에 따라 주문 취소를 처리합니다. 도구 매개변수를 고정하고, 실패한 도구 호출에서 복구하며, 다른 구조화된 절차를 호출한 다음 통화를 종료합니다.

```json maxLines=30
{
  "steps": [
    {
      "type": "ask",
      "instruction": "Ask the user for their order ID."
    },
    {
      "type": "branch",
      "branches": [
        {
          "condition": {
            "type": "llm",
            "condition": "The user says the order has already shipped."
          },
          "steps": [
            {
              "type": "tell",
              "instruction": "Explain that shipped orders must be returned before they can be refunded."
            }
          ]
        },
        {
          "condition": {
            "type": "llm",
            "condition": "The user says the order has not shipped."
          },
          "steps": [
            {
              "type": "tool_call",
              "tool_id": "tool_abc123",
              "tool_name": "cancel_order",
              "instruction": "Cancel the order using the order ID provided by the user.",
              "schema_overrides": {
                "request_body.notify_customer": { "source": "constant", "constant_value": true }
              },
              "on_failure": {
                "branches": [],
                "fallback": [
                  {
                    "type": "tell",
                    "instruction": "Apologize that the cancellation did not go through and say you will try once more."
                  },
                  {
                    "type": "retry",
                    "max_retries": 1
                  }
                ]
              }
            }
          ]
        }
      ],
      "fallback": [
        {
          "type": "ask",
          "instruction": "Ask whether the order has already shipped."
        }
      ]
    },
    {
      "type": "sub_procedure",
      "procedure_id": "agtprc_6qbpwdq8n01bxhk44bgjy6f10ck3"
    },
    {
      "type": "say",
      "message": "Thank you for contacting us. Goodbye.",
      "message_translations": {
        "es": { "value": "Gracias por contactarnos. Adiós." }
      }
    },
    {
      "type": "system_tool",
      "system_tool_name": "end_call"
    }
  ]
}
```

## 구조화된 절차의 실행 방식

구조화된 절차의 단계를 에이전트가 실행하는 형식으로 변환하는 것을 컴파일이라고 합니다. 플랫폼은 에이전트 초안을 저장하거나 에이전트를 게시할 때 모든 구조화된 절차를 컴파일하며, 작성자가 직접 컴파일할 일은 없습니다.

사용자의 요청이 절차의 트리거와 일치하면 플랫폼은 절차에 진입해 단계를 순서대로 실행합니다. 구조화된 절차 내부에서 에이전트는 각 단계에 개별적으로 집중합니다. 끝에 도달하면 플랫폼은 제어를 나머지 대화로 돌려줍니다.

워크플로 엣지는 구조화된 절차로 연결하거나 구조화된 절차에서 연결할 수 없습니다. 구조화된 절차를 연결하려면 Sub-procedure 단계를 사용하세요. 플랫폼은 일치하는 트리거에서의 진입과 완료를 관리하며, 절차가 시작된 워크플로 노드로 제어를 돌려주는 작업도 포함됩니다.

다음 규칙은 런타임에서 단계가 동작하는 방식을 설명합니다.

#### 사용자 입력을 기다리는 단계는 Ask뿐입니다

Ask 이외의 모든 단계는 즉시 실행되며, 제어는 동일한 턴 내에서 다음 단계로 이동합니다.
Tell 또는 Say 단계는 메시지를 전달하고 계속 진행합니다. Ask 외에 대화를 일시 중지하는
단계도, 현재 턴을 종료하는 단계도 없습니다. 사용자 입력이 필요하면 Ask 단계를
사용하세요. 대화를 종료해야 하면 `end_call` 시스템 도구를 사용하세요.

#### 절차의 끝에 도달해도 턴은 종료되지 않습니다

마지막 단계가 완료되면 절차가 끝나고 에이전트는 턴이 열린 상태로 나머지
대화로 돌아가므로 더 말할 수 있습니다. 하위 절차가 완료되면
제어는 이를 호출한 절차의 다음 단계로 돌아갑니다.

#### Tool 단계는 성공과 실패만 구분합니다

Tool 단계는 상태 코드나 응답 본문을 기준으로 분기할 수 없습니다. 도구가 성공하면
절차는 계속 진행됩니다. 실패하고 단계에 실패 핸들러가 없으면 대화가 종료됩니다. 실패 핸들러가
있으면 핸들러의 단계가 실행되고 절차는 다음 단계로 계속 진행됩니다. 핸들러 내 Retry는
도구를 다시 실행하고, 다시 실패하면 도구가 성공하거나 시도를 모두 사용할 때까지 핸들러의
모든 단계를 다시 실행합니다. 시도를 모두 사용하면 대화가 종료됩니다.

#### 일치하는 항목이 없으면 If 단계는 다음으로 진행됩니다

조건은 순서대로 평가되며 첫 번째 일치 항목이 실행됩니다. 일치하는 항목이 없으면 Else 분기가
실행됩니다. Else가 없고 일치하는 항목도 없으면 절차는 If 다음 단계로
계속 진행됩니다. 처리되지 않은 경우는 오류가 아닙니다.

#### If 분기는 상태를 이후 단계로 전달하지 않습니다

If 분기 안에서 결정된 내용은 이후 단계에 기억되지 않습니다. 분기에서 파악한 내용이
나중에 필요하면 도구 호출 또는 동적 변수로 명시적으로 유지하세요.

#### Ask, Tell, Say 단계에는 도구가 없습니다

도구를 호출할 수 있는 것은 Tool 단계뿐입니다. Ask, Tell 또는 Say 단계에 도구를 호출하지
말라고 지시할 필요가 없습니다. 호출할 수 없기 때문입니다.

## 구조화된 절차 관리

#### 대시보드에서 구축

[대시보드](https://elevenlabs.io/app/agents)에서 에이전트를 연 다음 **Procedures**를 선택하세요.
**+** 를 사용해 구조화된 절차를 만드세요. 트리거를 추가하고 각 단계의 유형을 선택한 후
에이전트 변경 사항을 게시하세요.

대시보드는 편집 중에 구조화된 절차를 검증합니다. 절차가
[검증 규칙](#validation-rules)을 위반하면 **Publish** 버튼에 오류 상태가 표시되고,
**Procedures** 탭에 오류 배지가 표시되며, 절차를 수정할 때까지 미리보기를 시작할 수
없습니다. 오류 표시기를 선택하면 영향을 받은 절차와 단계를 확인할 수 있습니다.

![오류 상태의 Publish 버튼과 1 Error
배지가 있는 구조화된 절차 편집기](/docs/_fern-files/_img/e406c33fac3966fab26d5d07e10d364a475fc4a56fd75aad2e23edbb0d1940d5.webp)

![실패한 절차와 메시지가 필요한 단계를 나열하는 검증 세부정보
대화 상자](/docs/_fern-files/_img/a1cc889b2d0e68ce23725609b531938d0f7c417b1c6f4375103531eaae4ada63.webp)

#### CLI에서 관리

[ElevenLabs CLI](/docs/ko/eleven-agents/operate/cli)는 자유 형식 절차와 동일한 명령으로 구조화된
절차를 생성하고 게시합니다. `type`을 `deterministic`으로 설정하고,
`content`에 JSON 인코딩 문자열로 단계를 전달하세요.

```bash
CONTENT=$(jq -n '{
  trigger: "When the user asks to refund an order",
  steps: [{ type: "ask", instruction: "Ask for the order ID." }]
}')

elevenlabs agents procedures create \
  --agent-id agent_7101k5zvyjhmfg983brhmhkd98n6 \
  --branch-id agtbranch_0901k4aafjxxfxt93gd841r7tv5t \
  --json "$(jq -n --arg content "$CONTENT" '{
    name: "Refund request",
    type: "deterministic",
    trigger: "When the user asks to refund an order",
    content: $content
  }')"

elevenlabs agents update \
  --agent-id agent_7101k5zvyjhmfg983brhmhkd98n6 \
  --branch-id agtbranch_0901k4aafjxxfxt93gd841r7tv5t \
  --json '{"version_description": "Publish refund procedure"}'
```

게시 작업은 브랜치의 모든 구조화된 절차를 검증합니다. 하나라도 유효하지 않으면 명령이
0이 아닌 코드로 종료되고 절차 ID별 오류를 출력합니다. 절차 초안을 수정하고 다시
게시하세요.

#### API에서 관리

API 및 SDK 페이로드에서는 구조화된 절차에 `type: "deterministic"`를 사용합니다. `content`는
JSON 인코딩 문서입니다.

### 사전 요구 사항

* `ELEVENLABS_API_KEY` 환경 변수에 설정된 ElevenLabs API 키.
* 대상 `agent_id` 및 `branch_id`. 브랜치 작업은 [에이전트 버전 관리](/docs/ko/eleven-agents/operate/versioning)를 참조하세요.
* `elevenlabs` Python 패키지 또는 `@elevenlabs/elevenlabs-js` JavaScript 패키지 버전 `2.60.0` 이상.

API 편집 내용은 새 에이전트 버전을 게시할 때까지 선택한 브랜치에서 사용자에게만 표시됩니다.

### 초안 생성 또는 업데이트

`POST /procedures`로 구조화된 절차를 생성하고 `type`을 `deterministic`으로 설정하세요.
아래와 같이 `PATCH /procedures/{procedure_id}/draft`로 기존 절차를 업데이트하세요.

`trigger`는 최상위 필드로 설정하세요. 중첩 객체를 전송하지 말고 단계 문서를 `content`에
JSON 인코딩하세요.

```python focus={6-18}
import json
from elevenlabs import ElevenLabs

elevenlabs = ElevenLabs()

elevenlabs.conversational_ai.agents.procedures.drafts.update(
    agent_id="agent_7101k5zvyjhmfg983brhmhkd98n6",
    branch_id="agtbranch_0901k4aafjxxfxt93gd841r7tv5t",
    procedure_id="agtprc_6qbpwdq8n01bxhk44bgjy6f10ck3",
    name="Refund request",
    type="deterministic",
    trigger="When the user asks to refund an order",
    content=json.dumps(
        {
            "steps": [{"type": "ask", "instruction": "Ask for the order ID."}],
        }
    ),
)
```

```typescript focus={5-17}
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const elevenlabs = new ElevenLabsClient();

await elevenlabs.conversationalAi.agents.procedures.drafts.update(
  "agent_7101k5zvyjhmfg983brhmhkd98n6",
  "agtbranch_0901k4aafjxxfxt93gd841r7tv5t",
  "agtprc_6qbpwdq8n01bxhk44bgjy6f10ck3",
  {
    name: "Refund request",
    type: "deterministic",
    trigger: "When the user asks to refund an order",
    content: JSON.stringify({
      steps: [{ type: "ask", instruction: "Ask for the order ID." }],
    }),
  }
);
```

```bash focus={1-9}
curl -X PATCH "https://api.elevenlabs.io/v1/convai/agents/agent_7101k5zvyjhmfg983brhmhkd98n6/branches/agtbranch_0901k4aafjxxfxt93gd841r7tv5t/procedures/agtprc_6qbpwdq8n01bxhk44bgjy6f10ck3/draft" \
  -H "xi-api-key: $ELEVENLABS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Refund request",
    "type": "deterministic",
    "trigger": "When the user asks to refund an order",
    "content": "{\"steps\":[{\"type\":\"ask\",\"instruction\":\"Ask for the order ID.\"}]}"
  }'
```

절차 초안을 저장해도 단계는 검증되지 않습니다. 게시하거나
`POST /v1/convai/agents/{agent_id}/drafts`로 에이전트 초안을 저장할 때 검증이 실행됩니다.

### 변경 사항 게시

[에이전트 업데이트](/docs/ko/api-reference/agents/update)로 게시하세요. 게시 작업은 브랜치의 모든
구조화된 절차를 검증하고, 모두 통과하면 새 버전에 절차를 게시합니다.
요청에는 `workflow` 필드가 필요하지 않습니다.

```python focus={5-8}
from elevenlabs import ElevenLabs

elevenlabs = ElevenLabs()

elevenlabs.conversational_ai.agents.update(
    agent_id="agent_7101k5zvyjhmfg983brhmhkd98n6",
    branch_id="agtbranch_0901k4aafjxxfxt93gd841r7tv5t",
)
```

```typescript focus={5-7}
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const elevenlabs = new ElevenLabsClient();

await elevenlabs.conversationalAi.agents.update("agent_7101k5zvyjhmfg983brhmhkd98n6", {
  branchId: "agtbranch_0901k4aafjxxfxt93gd841r7tv5t",
});
```

```bash focus={1-5}
curl -X PATCH \
  "https://api.elevenlabs.io/v1/convai/agents/agent_7101k5zvyjhmfg983brhmhkd98n6?branch_id=agtbranch_0901k4aafjxxfxt93gd841r7tv5t" \
  -H "xi-api-key: $ELEVENLABS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```

구조화된 절차가 유효하지 않으면 게시 작업은 `400`을 반환하며 아무것도 기록되지 않습니다.

```json
{
  "detail": {
    "status": "procedure_validation_failed",
    "message": "Structured procedures failed validation.",
    "data": {
      "errors": {
        "agtprc_6qbpwdq8n01bxhk44bgjy6f10ck3": [
          {
            "path": "steps[0].ask.instruction",
            "message": "Step 1: Ask step requires an instruction"
          }
        ]
      }
    }
  }
}
```

`errors`는 절차 ID별로 구성됩니다. 각 항목은 실패한 필드와 단계를 표시합니다. 절차
초안을 수정하고 다시 게시하세요.

초안 삭제 및 폐기 동작은 [절차 관리](/docs/ko/eleven-agents/customization/procedures#manage-procedures)를,
전체 엔드포인트 스키마는
[Procedures API 레퍼런스](/docs/ko/api-reference/agents/procedures/)를 참조하세요.

## 모범 사례

각 단계 유형은 자체 동작을 이미 강제하므로, 이를 굳이 명시할 필요는 거의 없습니다. 각 단계의 의도를 작성하고 나머지는 단계 유형에 맡기세요. 아래 지침에서는 제대로 설정하는 것이 중요한 경우를 다룹니다.

구조화된 프로시저를 테스트하려면 [프로시저 반복](/docs/ko/eleven-agents/customization/procedures/free-form-procedures#iterating-on-a-procedure)을 따르세요.

### 단계 유형 선택

#### Ask 단계마다 질문 하나씩 사용

Ask 단계는 하나의 답변을 기다립니다. 여러 질문을 하나의 지침에 묶으면
에이전트가 일부를 건너뛰거나 합치는 경향이 있습니다. 정보 항목마다 Ask를 하나씩 사용하세요.

#### 진술에는 Tell, 질문에는 Ask 사용

Tell 단계는 메시지를 전달한 후 기다리지 않고 다음으로 넘어갑니다. 질문 형태로 작성된 Tell은
답변을 받지 못합니다. 사용자 응답이 필요한 단계라면 Ask를 사용하세요.

#### 질문만으로 충분하지 않을 때 Ask에 명확한 종료 조건 지정

Ask 단계는 적절한 답변을 받으면 진행합니다. 어떤 답변이 적절한지 질문만으로
명확하지 않다면 지침에 명시하세요. 예: *주문 ID를 요청하세요. 유효한 ID는 8자리 숫자입니다*.

#### 표현 방식에는 Tell, 정확한 문구에는 Say 선택

에이전트가 메시지를 직접 구성해야 할 때는 Tell 단계를, 문구가 축자 그대로이거나 번역되어야 할 때는 Say 단계를 사용하세요.
두 단계 모두 정확히 하나의 메시지를 전달하므로, 단계에 단일 메시지를 보내라고
지시할 필요는 없습니다.

#### 도구를 사용하지 않는 단계에 도구 회피를 지시하지 않기

Ask, Tell, Say 단계는 도구를 호출할 수 없습니다. 여기에 \_어떤 도구도 호출하지 마세요_라고 작성해도
동작은 바뀌지 않고 지침에 불필요한 내용만 추가됩니다.

### 프로시저 구조화

#### 두 If 단계 사이에 불필요한 단계 추가하지 않기

두 If 단계는 연속해서 배치할 수 없습니다. 이 규칙을 충족하려고 관련 없는 Tell 또는 Say를 그 사이에 삽입하면
에이전트가 말하지 말아야 할 내용을 말하게 됩니다. 대신 두 번째 결정을 첫 번째 If에 추가 Else if 분기로
포함하거나 하위 프로시저로 옮기세요.

#### 중첩된 결정은 하위 프로시저에 배치

If 단계는 중첩할 수 없습니다. 한 결정이 다른 결정에 의존하는 경우, 내부 결정을 별도의
구조화된 프로시저에 넣고 필요한 분기에서 Sub-procedure 단계로 호출하세요.

#### '위 항목에 해당하지 않음'이 중요하면 Else 추가

Else가 없는 If 단계는 일치하는 항목이 없을 때 다음 단계로 넘어갑니다. 일치하지 않는
경우를 다르게 처리해야 한다면 해당 경우를 위한 Else 분기를 추가하세요.

#### 이후 단계에 필요한 정보 저장

If 분기 내에서 내린 결정은 이후에 기억되지 않습니다. 이후 단계가
분기에서 알게 된 정보에 의존한다면, 분기 내에서 도구 호출 또는 동적 변수로 이를 기록하세요.

#### 표현식 조건은 값을 채우는 도구 뒤에 배치

표현식 조건은 동적 변수를 테스트합니다. 이를 사용하는 If 단계는 해당 변수를 설정하는 Tool
단계 바로 뒤에 배치하세요. 사용자가 말한 내용을 기준으로 분기하려면 텍스트 조건을 사용하세요.

#### 공유 단계를 하위 프로시저로 추출

여러 구조화된 프로시저가 상담원 연결과 같은 동일한 순서를 공유한다면,
빈 트리거가 있는 하나의 구조화된 프로시저에 넣고 각각에서 호출하세요. 복사한 순서는
시간이 지나면 서로 달라집니다.

### 도구 사용

#### Tool 단계는 지침이 아닌 If로 제어

Tool 단계는 항상 해당 도구를 호출합니다. \_티켓에 이미 태그가 지정되어 있으면 건너뛰기_와 같이 지침에 작성한 조건은
호출을 막을 수 없습니다. 호출이 항상 필요한 것이 아니라면 Tool 단계 전에 If 단계에
조건을 넣으세요.

#### 매개변수 값은 설명 대신 고정

매개변수가 항상 특정 값을 가져야 한다면
`schema_overrides`에서 `constant` 재정의로 설정하세요. \_상태를 항상 pending으로 설정_과 같은 지침은 모델에
준수를 요청할 뿐이지만, 재정의는 강제되며 건너뛸 수 없습니다.

#### 모든 Tool 단계에 실패 처리기 지정

`on_failure`가 없으면 도구가 실패할 경우 대화가 종료됩니다. 사용자에게
발생한 일을 알리고 재시도, 에스컬레이션 또는 계속 진행하는 처리기를 추가하세요.

#### Tool 단계는 도구 호출에만 사용

Tool 단계는 도구만 실행하며, 이 단계 중에 에이전트는 말하거나 결정을 내릴 수 없습니다. 사용자에게 말하거나
도구 반환값을 기준으로 분기하려면 Tool 단계 전후에 별도의 단계로
배치하세요.

### 지침 작성

#### 현재 단계만 설명

프로시저는 다음에 실행될 작업을 제어하며, 에이전트는 현재 단계를 실행하는 동안
이후 단계를 알지 못합니다. 단계 순서에 따라 순서를 제어하세요.

#### 문장으로 턴 종료를 시도하지 않기

\_이것이 이번 턴의 마지막 메시지입니다_와 같이 단계 지침에 작성한 문장은
플랫폼에서 제공하지 않는 경계를 에이전트가 강제하도록 요청합니다. 사용자 응답을 기다리려면 Ask 단계를 사용하고,
대화를 끝내려면 `end_call` 시스템 도구를 사용하세요.

#### 전역 규칙은 시스템 프롬프트에 유지

어조, 서식, 맺음말 및 거부 정책은 [시스템 프롬프트](/docs/ko/eleven-agents/best-practices/prompting-guide)에 포함해야 합니다. 단계 지침에는 해당 단계에만
해당하는 내용만 작성하세요.

### 프로시저 조합

프로시저 조합에 대한 일반 지침은 구조화된 프로시저에도 적용됩니다. \[자유 형식 프로시저] 페이지의 [프로시저 조합](/docs/ko/eleven-agents/customization/procedures/free-form-procedures#composing-procedures)을 참조하세요.

유형을 혼합할 때는 한 가지 패턴이 적용됩니다. 자유 형식 프로시저는 구조화된 프로시저를 참조할 수 있습니다. 열린 형태의 처리는 자유 형식 프로시저에서 유지하고, 신원 확인이나 에스컬레이션처럼 매번 동일한 방식으로 실행되어야 하는 부분은 구조화된 프로시저에 맡기세요.

## 제한 사항

* If 단계는 중첩할 수 없으며, 두 If 단계를 연속해서 배치할 수 없습니다.
* 지원되는 시스템 도구는 `end_call`뿐입니다.
* 구조화된 프로시저는 지식 베이스 문서를 참조할 수 없습니다.
* 프로시저가 완료될 때 현재 턴을 종료하는 방법은 없습니다. 에이전트는 턴을 열린 상태로 유지하며 계속 말할 수 있습니다.
* 워크플로 에지는 구조화된 프로시저에 연결하거나 구조화된 프로시저에서 연결할 수 없습니다. 구조화된 프로시저를 연결하려면 Sub-procedure 단계를 사용하세요. 진입과 완료는 플랫폼에서 관리합니다.
* 프로시저를 시작하면 지연 시간이 추가됩니다. 에이전트가 진입을 위해 도구를 호출한 다음 생성된 워크플로를 진행하기 때문입니다.

### 모델 제공업체 지원

구조화된 프로시저는 하위 프로시저에 진입하고 프로시저를 완료할 때 내부 도구 호출을 강제합니다. 주요 OpenAI, Anthropic, Gemini, Grok 모델 제품군은 강제 도구 선택을 지원합니다. 다른 모델 또는 맞춤형 제공업체는 이를 보장하지 않을 수 있으며, 이 경우 하위 프로시저 전환 또는 프로시저 완료의 안정성이 떨어질 수 있습니다. 다른 모델 제공업체를 사용할 때는 강제 도구 선택 지원 여부를 확인하세요.

콘텐츠 크기 제한 및 구조화된 프로시저와 자유 형식 프로시저의 차이를 포함해 모든 프로시저에 적용되는 제한 사항은 [프로시저](/docs/ko/eleven-agents/customization/procedures#limitations)를 참조하세요.