Discourse 워크플로

:discourse2: 요약 Discourse Workflows는 관리자가 시각적 빌더를 통해 고급 자동화를 만들어 커뮤니티의 거의 모든 작업을 자동화할 수 있게 해줍니다.
:open_book: 설치 가이드 이 플러그인은 Discourse 코어에 번들로 포함되어 있습니다. 플러그인을 별도로 설치할 필요가 없습니다.

Workflows는 드래그 앤 드롭 캔버스를 사용하여 트리거, 조건, 액션, 흐름 제어 노드를 연결하여 고급 다단계 자동화를 만들 수 있는 시각적 자동화 빌더입니다. 이를 통해 Discourse 사이트의 거의 모든 것을 자동화할 수 있습니다.

:discourse: Discourse WorkflowsBusiness 또는 Enterprise 플랜에서 사용할 수 있습니다.

주요 개념

다른 자동화 도구에 익숙하다면 Workflows에서 사용되는 대부분의 용어를 알아볼 수 있을 것입니다:

  • 워크플로(Workflow): 연결된 노드로 구성된 저장된 자동화입니다.
  • 노드(Node): 워크플로의 단일 단계로, 트리거, 조건, 액션, 흐름 제어/유틸리티를 포함합니다.
  • 트리거(Trigger): 워크플로의 시작점입니다. 트리거는 수동으로 실행되거나 특정 이벤트(토픽 생성, 일정 실행, 수신 웹훅 등)에 의해 시작될 수 있습니다.
  • 조건(Condition): 규칙을 평가하고 흐름을 분기하는 라우팅 노드입니다. 예를 들어, If 노드는 참 또는 거짓 평가에 따라 흐름을 라우팅합니다.
  • 액션(Action): 특정 작업을 수행하는 노드입니다. 게시물 작성, 배지 부여, 외부 API 호출 등입니다.
  • 아이템(Item): 노드 사이를 흐르는 데이터입니다. 아이템은 실행 로그에서 확인할 수 있는 JSON 객체이며, 식을 사용하여 참조할 수 있습니다.
  • 식(Expression): 런타임에 해석되는 {{ ... }} 형식으로 작성되는 동적 값으로, 이전 노드의 데이터, 워크플로 변수 또는 사이트 설정을 참조하는 데 사용됩니다.

워크플로 생성

워크플로를 만들기 위해:

  1. 관리자 > 플러그인 > Workflows로 이동하여 새 워크플로를 클릭합니다.

  1. 워크플로 이름을 지정합니다.
  2. 첫 단계 추가를 클릭하고 트리거를 선택합니다.

  1. + 버튼을 사용하여 추가 노드를 만듭니다.

  1. 노드를 더블클릭하여 설정합니다. 설정 패널에서 노드의 입력에 대한 세부 사항은 화면 왼쪽에, 노드의 출력에 대한 세부 사항은 화면 오른쪽에 표시됩니다. 모든 세부 사항을 확인하려면 워크플로를 한 번 실행해야 할 수 있습니다.

  1. 공개할 준비가 되면 공개(Publish)를 클릭합니다.

:light_bulb: 팁:

  • 빌더 오른쪽 위 세 점 메뉴에 있는 **메모(sticky notes)**를 사용하여 워크플로가 수행하는 작업을 문서화하세요. 메모는 워크플로에 영향을 주지 않지만 템플릿과 공유 워크플로를 이해하기 쉽게 만듭니다.
  • 개발 중에는 로그 노드를 사용하여 워크플로의 동작에 영향을 주지 않고 디버그 값을 실행 로그로 전송하세요.
  • 워크플로를 JSON으로 내보내고 가져오기하여 팀원과 공유하거나 다른 사이트의 워크플로를 재현할 수 있습니다.

식과 동적 데이터

식을 받는 필드는 편집기에 {/} 버튼을 표시합니다. 이를 클릭하면 트리거와 이전 노드에서 사용할 수 있는 데이터를 탐색하고 참조를 삽입할 수 있습니다.

일반적인 식

반환 내용
{{ $json.topic.title }} 현재 아이템의 토픽 제목
{{ $json.post.url }} 현재 아이템의 게시물 URL
{{ $json.user.username }} 현재 아이템과 연결된 사용자의 사용자 이름
{{ $vars.my_variable }} my_variable이라는 워크플로 변수의 값
{{ $site_settings.title }} 사이트 제목
{{ $execution.id }} 현재 실행의 고유 ID
{{ $('Node Name').item.json.property }} 캔버스 이름으로 참조되는 특정 상위 노드의 출력

정적 및 동적 값

=로 시작하는 필드는 식으로 처리됩니다. 앞에 =가 없는 필드는 일반 텍스트로 처리됩니다. 식 선택기가 이를 자동으로 처리합니다.

워크플로 관리

기존 워크플로를 관리하는 데 도움이 되는 여러 기능이 있습니다.

실행(Executions)

워크플로가 실행될 때마다 Discourse는 실행을 기록합니다. Workflows → Executions로 이동하여 히스토리를 확인하세요.

각 실행은 완료된 날짜와 시간 및 상태를 표시합니다:

  • 완료(Completed): 오류 없이 완료까지 실행되었습니다.
  • 오류(Error): 특정 노드에서 실패했습니다. 실행을 클릭하여 오류와 그 원인이 된 데이터를 확인하세요.
  • 실행 중(Running): 현재 처리 중입니다.
  • 대기 중(Waiting): Wait 노드로 인해 일시 중지되었습니다. 폼, 모달, 채팅 승인에 대한 응답을 기다리거나, Call Workflow 노드가 서브 워크플로의 완료를 기다리는 중입니다.
  • 레이트 제한(Rate limited): 레이트 제한으로 인해 워크플로가 건너뛰었습니다.
  • 건너뜀(Skipped): 트리거가 발동되었지만 워크플로가 비공개 상태였습니다.

워크플로의 실행을 더 자세히 살펴보기 위해 표시(Show) 버튼을 클릭할 수 있습니다. 이는 워크플로의 각 단계와 이를 확장하여 정확한 세부 사항 및 해당 단계의 소요 시간을 볼 수 있게 해줍니다.

페이지 하단에서 워크플로의 전체 소요 시간을 볼 수 있습니다. 필요에 따라 공유 또는 문제 해결을 위해 로그를 내보내기(Export)할 수도 있습니다.

설정

Workflows → 설정 탭에서 다음을 수행할 수 있습니다:

  • 이 워크플로 실행 시 실패가 발생하면 트리거되어야 하는 오류 워크플로를 구성합니다. 워크플로에 오류 트리거가 있으면 해당 트리거에서 정의된 대로 오류를 처리합니다.
  • 일정 트리거의 시간대를 설정합니다. 이 값이 설정되지 않으면 워크플로는 기본적으로 사이트 시간대를 사용합니다.
  • 워크플로 삭제. :warning: 이는 영구적이므로 진행하기 전에 워크플로를 내보내는 것(워크플로 빌더 오른쪽 위 세 점 메뉴에서 접근 가능)을 고려하세요.

버전

워크플로를 업데이트할 때마다 이전 버전이 저장됩니다. 이를 통해 예상대로 작동하지 않은 변경 사항을 되돌리기(Revert)하기가 쉽습니다.

변수

변수는 단일 워크플로에 범위가 설정된 키-값 쌍입니다. 워크플로의 변수 패널에서 정의하고 {{ $vars.key_name }}을 사용하여 어디서나 참조할 수 있습니다. 워크플로 그래프를 편집하지 않고 변경할 수 있는 구성 값(예: 카테고리 ID 또는 수신자 사용자 이름)을 저장하는 데 변수를 사용하세요.

자격 증명(Credentials)

HTTP 요청 또는 AI Agent와 같은 일부 노드는 외부 서비스와 인증해야 합니다. API 키와 시크릿을 노드 필드에 직접 붙여 넣지 않고 Workflows → Credentials에 저장하세요. 자격 증명은 저장 시 암호화되며 워크플로 간에 재사용할 수 있습니다.

지원되는 자격 증명 유형:

  • 기본 인증(Basic Auth) (사용자 이름 + 비밀번호)
  • Bearer 토큰
  • 헤더 인증(Header auth) (사용자 지정 헤더 이름 및 값)

데이터 테이블

데이터 테이블은 Workflows 플러그인 내부의 영구적이고 구조화된 테이블입니다. 데이터 테이블 노드를 사용하여 읽기 또는 쓰기 작업을 수행합니다. string, number, boolean, date 컬럼 유형을 지원합니다.

데이터 테이블은 다음에 유용합니다:

  • 중복 제거(Deduplication) — 워크플로가 이미 처리한 사용자 또는 토픽을 기록
  • 상태(State) — 토픽이 프로세스의 특정 단계에 있는지 추적
  • 조회(Lookups) — 워크플로에서 조회할 수 있는 매핑(예: 토픽 ID → 담당 스태프)을 저장

실행(Executions)

Executions 탭에서 모든 워크플로의 모든 실행을 볼 수 있습니다. 형식과 기능은 워크플로별 실행과 매우 유사하지만, 모니터링이 더 쉽도록 모든 워크플로에 걸쳐 표시됩니다.

템플릿

새 워크플로를 만들 때 빈 캔버스 대신 템플릿을 시작점으로 사용할 수 있습니다. 템플릿은 일반적인 사용 사례를 위한 사전 제작된 워크플로이며, 작동 방식을 설명하는 메모로 주석이 달려 있어 시스템을 배우는 좋은 방법입니다.

:megaphone: 더 많은 템플릿을 보고 싶으신가요? 사용 가능한 템플릿 라이브러리를 점차 확장할 계획이지만, Workflows 사용을 더 쉽게 만들기 위해 여기에서 보고 싶은 템플릿이 있다면 알려주세요.

또한 워크플로를 JSON 파일로 내보내어 다른 사람과 공유하거나 자신의 시작점으로 사용할 수도 있습니다.

22개의 좋아요

안녕하세요, 이 플러그인을 활성화하려고 하면 다음과 같은 오류 메시지가 표시됩니다: “숨겨진 설정을 변경할 권한이 없습니다: discourse_workflows_enabled”

2개의 좋아요

현재는 admin/plugins가 아니라 /admin/config/upcoming-changes에서 활성화해야 합니다.

3개의 좋아요

안녕하세요, 워크플로우의 목적을 제가 제대로 이해하고 있다면, 원하시는 템플릿 예시 중 하나는 주제에 관리자 버튼을 추가하여 즉시 해당 주제를 상단으로 올리는 것일 것입니다. 실현 가능한가요? :grinning_face:

1개의 좋아요

안녕하세요!

"Build with AI"에서 특정 LLM을 사용하도록 어떻게 보장할 수 있을까요?
시스템에서 기본 LLM로 Google Gemini를 사용할 때 다음과 같은 오류가 발생합니다: Invalid JSON payload received. Unknown name “additionalProperties” at ‘tools[0].function_declarations[5].parameters’: Cannot find field

감사합니다!

1개의 좋아요

어떤 Gemini 모델을 사용 중인가요? 변경하려면 워크플로 에이전트를 선택하고那里的 기본 LLM을 교체하면 됩니다.

1개의 좋아요

샘! Gemini 3 Flash입니다.

워크플로 설정을 찾아봤는데, 역시 Gemini Flash 3로 설정되어 있더라고요. GPT Nano 5로 변경해 봤는데도 같은 오류가 발생합니다.

모든 사용자의 기본값을 GPT Nano 5로 변경하고 개별 워크플로 설정도 확인해 봤습니다. 거기서도 GPT Nano 5로 덮어쓰도록 설정해 봤는데도,

여전히 해결되지 않습니다. :frowning:

1개의 좋아요

Luna나 Terra, 또는 3.5 flash나 sonnet에 접근할 수 있을까요?

워크플로 AI 에이전트는 도구가 꽤 많아서 최신 LLM이 필요할 가능성이 큽니다.

1개의 좋아요

Flash Lite가 작동하는 줄 알았는데, 실제로는 작동하지 않았습니다. GPT Nano 5는 확실히 작동했습니다. 이는 WordPress에서도 알려진 문제인 것 같습니다. 참고 링크를 아래에 공유합니다. 우리가 해야 할 일은 Gemini 제공자를 사용할 때마다 JSON 응답 스키마에서 additionalProperties 항목을 제거하는 것입니다: Remove `additionalProperties` from the JSON response schema - Pull Request #18 - WordPress/ai-provider-for-google - GitHub

야, interactions API로 마이그레이션을 진행 중인데, 이렇게 하면 Gemini 모델로 훨씬 안정적인 브리지를 제공할 수 있을 것 같아. 다음 주에 가능할 거야.

2개의 좋아요

대단하고 빠른 답변 감사합니다! 더 많은 내용을 찾았지만, 이미 의도를 파악하셨을 거라고 생각합니다. :wink:

이것은 Google의 Gemini가 직접 작성한 설명입니다. 이해가 되시나요? 저도 전부 이해는 못하지만, 그 프로퍼티 때문에 막힌다는 것만은 압니다. ㅋㅋ

요약: Google이 스키마 처리를 위해 완전히 다른 두 가지 엔진을 사용하기 때문에 오류가 지속됩니다. Gemini는 구조화된 출력(Structured Outputs)(response_json_schema)의 경우 표준 JSON 스키마를 지원하지만, 함수 호출/도구 실행(Function Calling / Tool Execution) 엔진은 여전히 Google의 엄격한 OpenAPI 3.0 Protobuf 파서를 사용하며, 이는 additionalProperties를 거부하거나 처리하지 못합니다.

1. 도구 호출 vs. 구조화된 출력 (엔진 분기)

Google의 Gemini API는 두 가지 별도의 위치에서 스키마를 검증합니다:

  • 구조화된 출력(response_json_schema): 모델의 최종 응답 형식을 지정하는 용도로 설계되었습니다. 표준 JSON 스키마 파싱을 사용하며 additionalProperties를 깔끔하게 처리합니다.

  • 도구/함수 호출(tools[0].function_declarations): 사이트 도구(Discourse AI 검색, 페르소나 액션, 웹 브라우징 등)를 모델에 전달하는 용도로 설계되었습니다. 이 엔드포인트는 스키마를 Google의 내부 google.ai.generativelanguage.v1beta.Schema Protobuf 객체로 파싱합니다.

도구 엔드포인트가 매개변수를 레거시 OpenAPI 3.0 하위 집합으로 매핑하기 때문에, 함수 선언에 additionalProperties를 보내면 API 파서가 400 Bad Request 또는 MALFORMED_FUNCTION_CALL을 반환합니다.

GitHub

2. 왜 Discourse와 같은 프레임워크가 이를 주입하는가

오케스트레이션 프레임워크(Discourse AI, Model Context Protocol/MCP, LangChain, Pydantic, Zod)는 사용자 정의 도구를 위해 JSON 스키마를 자동으로 생성합니다:

  1. 엄격한 강제 기본값: 생성기는 엄격한 매개변수 타입을 강제하기 위해 자동으로 "additionalProperties": false를 추가합니다.

  2. 동적 맵/딕셔너리: 도구 매개변수가 키-값 해시/딕셔너리(예: dict[str, Any] 또는 Ruby Hash)를 사용하는 경우, 스키마 생성기는 "additionalProperties": { "type": "string" }를 출력합니다.

  3. 비정제된 페이로드: Discourse가 이러한 자동 생성된 도구 스키마를 Google의 함수 선언 엔드포인트로 전송할 때, Gemini의 Protobuf 파서는 additionalProperties를 무효하거나 알려지지 않은 필드로 표시합니다.

3. Discourse에서 해결하는 방법

Discourse AI 도구 호출에서 이 오류를 보고 계신다면:

  • 동적 해시/딕트 매개변수 피하기: 열려 있는 객체를 사용하는 대신, 사용자 정의 도구 매개변수가 properties 아래에 예상되는 모든 키를 명시적으로 정의하도록 하세요.

  • 동적 데이터를 문자열로 직렬화: 도구가 임의의 키-값 쌍을 받아야 하는 경우, 매개변수를 STRING으로 정의하고 도구가 직렬화된 JSON 문자열을 받도록 지시하세요.

  • 사용자 정의 도구에서 additionalProperties 필터링: /admin/plugins/discourse-ai/ai-tools 아래에 사용자 정의 AI 도구를 정의한 경우, 매개변수 JSON 스키마를 편집하여 모든 "additionalProperties" 블록을 제거하세요.

방금 인터랙션 API 지원을 추가하는 PR을 만들었습니다. 테스트 환경이 있으시면 더 많은 테스트를 진행해 주시면 좋겠습니다.

워크플로우를 통해 외부 사용자 ID를 가져올 수 있도록 할 계획이 있나요? 현재 사용자가 계속 진행하기 전에 아이덴티티 제공자 시스템에서 해당 사용자의 일부 정보를 확인하는 양식을 만들고 싶은데, 제가 확인한 바로는 ‘Get User’ 노드에서 external_id 필드가 출력되지 않습니다.

피드백 감사합니다. 이제 해결될 것 같습니다: FIX: supports optional data for workflow user node (#42400) · discourse/discourse@4d0c688 · GitHub

3개의 좋아요

user_id를 username으로 변환하는 방법이 있을까요? 특정 토픽의 생성자에게 개인 메시지를 보내는 사용 사례를 조사하고 있습니다. 하지만 topic 객체에서는 user_id만 가져올 수 있고, 개인 메시지 전송 동작에는 username이 필요합니다.

혹시 topic_id를 사용해 첫 번째 게시물을 가져오는 방법이 있다면 그것도 작동할 것 같습니다. 게시물에는 username 필드가 있으니까요.

1개의 좋아요

@thgl 네, data-explorer 노드가 있으므로 모든 종류의 정보를 가져오기 위한 다양한 쿼리가 가능합니다(이 경우 user_id를 하드코딩했지만, 개념을 이해하셨을 것입니다):

workflow-nodes-2026-08-18.json (2.1 KB)

2개의 좋아요

@patrickemin 이미 보셨을 수도 있지만, 이 사용 사례에 필요한 모든 빌딩 블록을 추가해 두었습니다. 도움이 필요하시면 말씀해 주세요.

1개의 좋아요

아, 정말 유용하네요. 감사합니다!

글쎄요, 해당 사용 사례에 대해 관리자 주제 버튼에 할당할 작업을 찾지 못했습니다: