Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

응답을 스트리밍하며 대화 추가(Streaming Continue Session) (V2)

세션에 사용자 메시지를 추가하고 Agent가 응답을 생성하는 동안 Markdown 텍스트를 스트리밍으로 받습니다. 정상적으로 스트림을 모두 받은 뒤에는 Get Content로 최종 대화 결과와 변수 변경값을 조회합니다.

같은 세션의 대화를 동시에 이어갈 수 없습니다. 응답이 끝나거나 진행 중인 대화를 취소한 뒤 다음 메시지를 보냅니다. 취소하려면 스트리밍 요청에 클라이언트가 생성한 messageId UUID를 넣어 두어야 합니다.

이 엔드포인트는 미리보기 기능이며 언제든 변경되거나 제거될 수 있습니다. 사용하려면 preview=true를 지정합니다.

HTTP 요청

POST /api/v2/aipAgents/agents/{agentRid}/sessions/{sessionRid}/streamingContinue

작업 식별자는 v2.streamingContinueSession입니다. OAuth2로 호출하는 타사 애플리케이션에는 api:aip-agents-write 권한 범위가 필요합니다. 각 요청에 Authorization: Bearer <접근 토큰>을 전달합니다.

경로 매개변수

이름자료형필수 여부의미와 조건예시 값
agentRidstring필수AIP Chatbot Studio에서 만든 챗봇의 Agent RID입니다.ri.aip-agents..agent.732cd5b4-7ca7-4219-aabb-6e976faf63b1
sessionRidstring필수대화 세션의 RID입니다.ri.aip-agents..session.292db3b2-b653-4de6-971c-7e97a7b881d6

쿼리 매개변수

이름자료형필수 여부의미와 조건예시 값
previewboolean선택미리보기 기능 사용을 활성화합니다.true

요청 본문

StreamingContinueSessionRequest 본문은 필수입니다. parameterInputs는 해당 Agent 버전의 변수 정의와 맞아야 합니다. contextsOverride를 지정하면 자동 검색을 건너뛰며, 생략하면 구성한 데이터 소스에서 검색합니다. 빈 배열과 필드 생략을 구분합니다.

이름자료형필수 여부의미와 조건예시 값
userInputobject필수Agent가 응답할 사용자 메시지입니다.본문 예시 참조
parameterInputsmap<ParameterId, ParameterValue>선택이번 대화에서 Agent에 전달할 애플리케이션 변수 값입니다.본문 예시 참조
contextsOverridelist<InputContext>선택지정하면 자동 컨텍스트 검색을 건너뛰고 전달한 목록을 Agent에 제공합니다. 생략하면 이 세션의 Agent에 구성한 데이터 소스에서 사용자 메시지와 관련된 컨텍스트를 자동 검색하여 프롬프트에 포함합니다.
messageIdstring선택클라이언트가 생성한 메시지 UUID입니다. 스트리밍 응답이 끝나기 전에 이 값으로 해당 대화를 취소할 수 있습니다.00f8412a-c29d-4063-a417-8052825285a5
sessionTraceIdstring선택이번 대화의 추적 ID입니다. 클라이언트가 생성하여 전달하면 응답 생성 중에 별도 요청으로 추적을 조회할 수 있습니다. 생략하면 자동 생성하며 Get Content로 가져온 SessionExchangeResult.sessionTraceId에서 확인합니다.12345678-1234-5678-1234-123456789abc

userInput의 구조

이름자료형필수 여부의미와 조건예시 값
textstring필수사용자 메시지의 텍스트입니다.What is the status of my order?

parameterInputs의 구조

맵의 키는 ParameterId(string), 값은 ParameterValue(union<string, objectSet>)입니다.

키: AIP Chatbot Studio에서 구성한 애플리케이션 상태 변수의 고유 식별자입니다.

Agent의 애플리케이션 상태에 구성한 변수에 전달하는 값입니다.

분기 string

StringParameter 애플리케이션 변수의 문자열 값입니다.

이름자료형필수 여부의미와 조건예시 값
typeenum필수분기를 구분하는 type 값입니다. 허용값: string.string
valuestring필수Titan Technologies
분기 objectSet

ObjectSetParameter 애플리케이션 변수에 전달하는 값입니다.

이름자료형필수 여부의미와 조건예시 값
typeenum필수분기를 구분하는 type 값입니다. 허용값: objectSet.objectSet
objectSetObjectSet필수온톨로지의 객체 집합 정의입니다.
ontologystring필수입력 ObjectSet이 속한 온톨로지의 API 이름입니다. List ontologies API나 Ontology Manager에서 확인합니다.
objectSet의 구조

ObjectSet의 15가지 구성 방식과 중첩 필드는 객체 집합 정의를 따릅니다. 조건식은 검색 조건, 속성 선택은 속성 식별자와 로드 수준, 계산 필드는 파생 속성, 공간 조건은 공간 필터를 사용합니다. 실험적 분기와 각 연산의 한도 및 입력 조건도 함께 적용합니다.

contextsOverride의 구조

배열 항목은 InputContext이며 자료형은 union<functionRetrievedContext, objectContext>입니다.

세션을 이어갈 때 Agent에 제공하는 사용자 지정 검색 컨텍스트입니다.

분기 functionRetrievedContext

Agent 프롬프트에 추가하기 위해 함수를 실행하여 얻은 컨텍스트입니다.

이름자료형필수 여부의미와 조건예시 값
typeenum필수분기를 구분하는 type 값입니다. 허용값: functionRetrievedContext.functionRetrievedContext
functionRidstring필수함수의 고유 리소스 식별자이며 다른 Foundry API와 연계할 때 사용합니다.ri.function-registry.main.function.8cb2d957-f0e6-4e0c-81de-e701bd54b18c
functionVersionstring필수함수 버전은 <major>.<minor>.<patch>-<tag> 형식이며 -<tag>는 생략할 수 있습니다. 예: 1.2.3, 1.2.3-rc1.1.2.3
retrievedPromptstring필수컨텍스트 검색 함수가 반환한 문자열입니다.
분기 objectContext

사용자 메시지에 대한 추가 컨텍스트로 프롬프트에 포함할 객체 인스턴스 정보입니다.

이름자료형필수 여부의미와 조건예시 값
typeenum필수분기를 구분하는 type 값입니다. 허용값: objectContext.objectContext
objectRidslist<ObjectRid>선택프롬프트에 포함할 관련 객체 인스턴스의 RID 목록입니다.
propertyTypeRidslist<PropertyTypeRid>선택해당 객체에서 프롬프트에 포함할 속성 유형의 RID 목록입니다.
objectRids의 구조

배열 항목은 ObjectRid이며 자료형은 string입니다.

객체의 고유 리소스 식별자이며 다른 Foundry API와 연계할 때 사용합니다.

propertyTypeRids의 구조

배열 항목은 PropertyTypeRid이며 자료형은 string입니다.

속성의 고유 리소스 식별자입니다.

다음 본문의 식별자와 값은 가상 예시입니다.

{
  "sessionTraceId": "12345678-1234-5678-1234-123456789abc",
  "messageId": "00f8412a-c29d-4063-a417-8052825285a5",
  "userInput": {
    "text": "What is the status of my order?"
  },
  "parameterInputs": {
    "currentCustomerOrders": {
      "type": "objectSet",
      "ontology": "example-ontology",
      "objectSet": {
        "type": "filter",
        "objectSet": {
          "type": "base",
          "objectType": "customerOrder"
        },
        "where": {
          "type": "eq",
          "field": "customerId",
          "value": "123abc"
        }
      }
    }
  }
}

응답

응답 본문은 Markdown 텍스트의 바이트 스트림입니다. JSON 응답 객체나 SSE의 data: 이벤트로 파싱하지 않습니다. 스트림의 텍스트만으로 변수 변경값이나 최종 컨텍스트를 구성하지 말고 완료 후 Get Content를 조회합니다.

sessionTraceId를 요청에 넣으면 생성 중 추적을 별도로 조회할 수 있습니다. 생략했다면 완료한 대화의 결과에서 자동 생성한 추적 ID를 읽습니다.

개별 오류

오류 이름오류 코드HTTP의미와 조건추가 매개변수
ObjectTypeIdsNotFoundNOT_FOUND404Agent에 구성한 객체 유형 중 일부를 찾을 수 없습니다. 객체 유형이 없거나 호출 토큰으로 접근할 수 없는 경우입니다. API에서 접근 가능한 객체 유형을 나열하거나 Ontology Manager에서 검색하여 확인합니다.agentRid, sessionRid, objectTypeIds
ObjectTypeRidsNotFoundNOT_FOUND404Agent에 구성한 객체 유형 중 일부를 찾을 수 없습니다. 객체 유형이 없거나 호출 토큰으로 접근할 수 없는 경우입니다. API에서 접근 가능한 객체 유형을 나열하거나 Ontology Manager에서 검색하여 확인합니다.agentRid, sessionRid, objectTypeRids
FunctionLocatorNotFoundNOT_FOUND404Agent에 구성한 함수 식별 정보를 찾을 수 없습니다. 해당 함수 유형이나 버전이 없거나 호출 토큰으로 접근할 수 없는 경우입니다.agentRid, sessionRid, functionRid, functionVersion
InvalidParameterINVALID_ARGUMENT400이 세션의 Agent에 유효하지 않은 애플리케이션 변수를 전달했습니다. getSession으로 세션의 Agent 버전을 확인한 뒤, 해당 버전의 getAgent.parameters 또는 AIP Chatbot Studio에서 변수 정의를 확인합니다.agentRid, sessionRid, parameter
InvalidParameterTypeINVALID_ARGUMENT400입력값이 이 세션의 Agent에 구성한 변수 유형과 맞지 않습니다. getSession으로 Agent 버전을 확인한 뒤, 해당 버전의 getAgent.parameters 또는 AIP Chatbot Studio에서 변수 정의를 확인합니다.agentRid, sessionRid, parameter, expectedType, receivedType
SessionTraceIdAlreadyExistsINVALID_ARGUMENT400해당 세션에서 이미 사용한 추적 ID입니다. 같은 ID를 다시 사용할 수 없습니다.agentRid, sessionRid, sessionTraceId
OntologyEntitiesNotFoundNOT_FOUND404Agent에 구성한 온톨로지 유형 중 일부를 찾을 수 없습니다. 유형이 없거나 호출 토큰으로 접근할 수 없는 경우입니다. API의 객체 유형 및 링크 유형 목록이나 Ontology Manager에서 확인합니다.agentRid, sessionRid, objectTypeRids, linkTypeRids
UnsupportedLanguageModelRidINVALID_ARGUMENT400Agent에 구성한 언어 모델을 지원하지 않거나 확인할 수 없습니다. 모델이 사용 중단되었거나 호출 토큰으로 접근할 수 없으면 실행 중에도 발생할 수 있습니다. AIP Chatbot Studio에서 Agent의 언어 모델을 갱신합니다.agentRid, sessionRid, languageModelRid, modelPurpose
ActionTypeNotFoundINVALID_ARGUMENT400Agent의 액션 도구가 참조한 액션 유형을 찾을 수 없습니다. 액션 유형이 삭제되었거나 호출 토큰으로 접근할 수 없으면 실행 중에도 발생할 수 있습니다. 유형의 존재 여부와 접근 권한을 확인한 뒤 AIP Chatbot Studio의 도구 구성을 점검합니다.agentRid, sessionRid, actionRid
StreamingContinueSessionPermissionDeniedPERMISSION_DENIED403세션에서 스트리밍 방식으로 대화를 이어갈 수 없습니다.agentRid, sessionRid
SessionNotFoundNOT_FOUND404지정한 세션을 찾을 수 없습니다.agentRid, sessionRid
AgentNotFoundNOT_FOUND404지정한 Agent를 찾을 수 없습니다.agentRid

요청 예제

FOUNDRY_HOST에는 https://를 제외한 Foundry 호스트를, FOUNDRY_TOKEN에는 유효한 토큰을 환경 변수로 제공합니다. 예시 식별자와 입력값은 실제 세션과 Agent 구성에 맞게 바꿉니다.

예시는 Agent에 객체 집합 변수 currentCustomerOrders를 구성한 경우입니다. example-ontology, customerOrder, customerId와 고객 값은 실제 온톨로지 API 이름, 객체 유형 및 속성 API 이름, 조회 값으로 바꿉니다. 세션에 연결된 버전의 변수 정의를 먼저 확인합니다. sessionTraceId는 매 대화마다 새 값으로 바꾸며 같은 세션에서 재사용하지 않습니다. messageId는 이 스트리밍 요청을 위해 생성한 UUID로 바꾸고 취소 요청에도 같은 값을 사용합니다.

AGENT_RESPONSE_FILE에는 Markdown 응답을 저장할 파일 경로를 지정합니다. 기존 파일은 덮어씁니다. 예제는 전체 응답을 메모리에 모으지 않고 본문 바이트를 파일에 기록합니다. 연결이 끊기거나 오류가 나면 파일에 일부 응답만 남을 수 있으므로 최종 대화 상태는 Get Content로 확인합니다.

cURL

curl --fail --no-buffer --output "${AGENT_RESPONSE_FILE}" -X POST \
	-H "Content-type: application/json" \
	-H "Authorization: Bearer ${FOUNDRY_TOKEN}" \
	"https://${FOUNDRY_HOST}/api/v2/aipAgents/agents/ri.aip-agents..agent.732cd5b4-7ca7-4219-aabb-6e976faf63b1/sessions/ri.aip-agents..session.292db3b2-b653-4de6-971c-7e97a7b881d6/streamingContinue?preview=true" \
	-d '{"sessionTraceId":"12345678-1234-5678-1234-123456789abc","messageId":"00f8412a-c29d-4063-a417-8052825285a5","userInput":{"text":"What is the status of my order?"},"parameterInputs":{"currentCustomerOrders":{"type":"objectSet","ontology":"example-ontology","objectSet":{"type":"filter","objectSet":{"type":"base","objectType":"customerOrder"},"where":{"type":"eq","field":"customerId","value":"123abc"}}}}}'

Python

Requests 라이브러리가 설치된 환경에서 사용합니다. with 블록이 종료되면 응답 연결과 출력 파일을 닫습니다.

import os
import requests

HOSTNAME = os.environ["FOUNDRY_HOST"]
TOKEN = os.environ["FOUNDRY_TOKEN"]
headers = {
    "content-type": "application/json",
    "authorization": "Bearer {}".format(TOKEN)
}
request_body = {
    "sessionTraceId": "12345678-1234-5678-1234-123456789abc",
    "messageId": "00f8412a-c29d-4063-a417-8052825285a5",
    "userInput": {
        "text": "What is the status of my order?"
    },
    "parameterInputs": {
        "currentCustomerOrders": {
            "type": "objectSet",
            "ontology": "example-ontology",
            "objectSet": {
                "type": "filter",
                "objectSet": {
                    "type": "base",
                    "objectType": "customerOrder"
                },
                "where": {
                    "type": "eq",
                    "field": "customerId",
                    "value": "123abc"
                }
            }
        }
    }
}

with requests.post('https://{}/api/v2/aipAgents/agents/ri.aip-agents..agent.732cd5b4-7ca7-4219-aabb-6e976faf63b1/sessions/ri.aip-agents..session.292db3b2-b653-4de6-971c-7e97a7b881d6/streamingContinue?preview=true'.format(HOSTNAME), headers=headers, json=request_body, stream=True) as response:
    response.raise_for_status()
    with open(os.environ["AGENT_RESPONSE_FILE"], "wb") as output:
        for chunk in response.iter_content(chunk_size=None):
            output.write(chunk)

Java

Apache HttpClient 4.5 API를 사용하는 StreamingContinueSessionExample.java 예제입니다.

import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;

public class StreamingContinueSessionExample {
    public static void main(String[] args) throws Exception {
        String HOSTNAME = System.getenv("FOUNDRY_HOST");
        String TOKEN = System.getenv("FOUNDRY_TOKEN");

        try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
            HttpPost request = new HttpPost("https://" + HOSTNAME + "/api/v2/aipAgents/agents/ri.aip-agents..agent.732cd5b4-7ca7-4219-aabb-6e976faf63b1/sessions/ri.aip-agents..session.292db3b2-b653-4de6-971c-7e97a7b881d6/streamingContinue?preview=true");
            request.addHeader("content-type", "application/json");
            request.addHeader("authorization", String.format("Bearer %s", TOKEN));
            request.setEntity(new StringEntity("{\"sessionTraceId\":\"12345678-1234-5678-1234-123456789abc\",\"messageId\":\"00f8412a-c29d-4063-a417-8052825285a5\",\"userInput\":{\"text\":\"What is the status of my order?\"},\"parameterInputs\":{\"currentCustomerOrders\":{\"type\":\"objectSet\",\"ontology\":\"example-ontology\",\"objectSet\":{\"type\":\"filter\",\"objectSet\":{\"type\":\"base\",\"objectType\":\"customerOrder\"},\"where\":{\"type\":\"eq\",\"field\":\"customerId\",\"value\":\"123abc\"}}}}}", ContentType.APPLICATION_JSON));
            try (CloseableHttpResponse response = httpClient.execute(request)) {
                int status = response.getStatusLine().getStatusCode();
                if (status < 200 || status >= 300) {
                    throw new IOException("HTTP " + status);
                }
                try (OutputStream output = Files.newOutputStream(
                        Paths.get(System.getenv("AGENT_RESPONSE_FILE")))) {
                    response.getEntity().writeTo(output);
                }
            }
        }
    }
}

JavaScript

fetch와 Node.js 스트림 API를 제공하는 환경의 ES 모듈(.mjs)에서 사용합니다. 서비스 사용자 토큰을 브라우저로 전달하지 않습니다.

import { createWriteStream } from "node:fs";
import { Readable } from "node:stream";
import { pipeline } from "node:stream/promises";

const HOSTNAME = process.env.FOUNDRY_HOST;
const TOKEN = process.env.FOUNDRY_TOKEN;

const response = await fetch(`https://${HOSTNAME}/api/v2/aipAgents/agents/ri.aip-agents..agent.732cd5b4-7ca7-4219-aabb-6e976faf63b1/sessions/ri.aip-agents..session.292db3b2-b653-4de6-971c-7e97a7b881d6/streamingContinue?preview=true`, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${TOKEN}`,
    },
    body: '{"sessionTraceId":"12345678-1234-5678-1234-123456789abc","messageId":"00f8412a-c29d-4063-a417-8052825285a5","userInput":{"text":"What is the status of my order?"},"parameterInputs":{"currentCustomerOrders":{"type":"objectSet","ontology":"example-ontology","objectSet":{"type":"filter","objectSet":{"type":"base","objectType":"customerOrder"},"where":{"type":"eq","field":"customerId","value":"123abc"}}}}}'
 });
if (!response.ok) {
    throw new Error(`HTTP ${response.status}`);
}
await pipeline(
    Readable.fromWeb(response.body),
    createWriteStream(process.env.AGENT_RESPONSE_FILE)
);

PowerShell

PowerShell 7에서는 .NET HttpClient의 ResponseHeadersRead로 헤더를 받은 뒤 본문을 복사합니다. $ErrorActionPreference = 'Stop'으로 HTTP 상태 검사나 복사 중 오류가 발생하면 스크립트를 실패로 종료하고, finally에서 연결과 파일을 닫습니다. 이 모드에서는 HttpClient의 제한 시간이 헤더 수신까지만 적용되므로, 애플리케이션에서 본문 읽기 제한 시간과 사용자 취소를 별도로 다룹니다.

$ErrorActionPreference = 'Stop'
$TOKEN = $env:FOUNDRY_TOKEN
$HOSTNAME = $env:FOUNDRY_HOST
$body = @'
{"sessionTraceId":"12345678-1234-5678-1234-123456789abc","messageId":"00f8412a-c29d-4063-a417-8052825285a5","userInput":{"text":"What is the status of my order?"},"parameterInputs":{"currentCustomerOrders":{"type":"objectSet","ontology":"example-ontology","objectSet":{"type":"filter","objectSet":{"type":"base","objectType":"customerOrder"},"where":{"type":"eq","field":"customerId","value":"123abc"}}}}}
'@

$client = [System.Net.Http.HttpClient]::new()
$request = $null
$response = $null
$stream = $null
$output = $null
try {
    $request = [System.Net.Http.HttpRequestMessage]::new(
        [System.Net.Http.HttpMethod]::Post,
        "https://$HOSTNAME/api/v2/aipAgents/agents/ri.aip-agents..agent.732cd5b4-7ca7-4219-aabb-6e976faf63b1/sessions/ri.aip-agents..session.292db3b2-b653-4de6-971c-7e97a7b881d6/streamingContinue?preview=true"
    )
    $request.Headers.Authorization = [System.Net.Http.Headers.AuthenticationHeaderValue]::new("Bearer", $TOKEN)
    $request.Content = [System.Net.Http.StringContent]::new(
        $body, [System.Text.Encoding]::UTF8, "application/json"
    )
    $response = $client.SendAsync(
        $request, [System.Net.Http.HttpCompletionOption]::ResponseHeadersRead
    ).GetAwaiter().GetResult()
    [void] $response.EnsureSuccessStatusCode()
    $stream = $response.Content.ReadAsStreamAsync().GetAwaiter().GetResult()
    $output = [System.IO.File]::Create($env:AGENT_RESPONSE_FILE)
    $stream.CopyToAsync($output).GetAwaiter().GetResult()
}
finally {
    foreach ($resource in @($output, $stream, $response, $request, $client)) {
        if ($null -ne $resource) { $resource.Dispose() }
    }
}