> For the complete documentation index, see [llms.txt](https://docs.axid.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.axid.app/ko/guides/concepts.md).

# 핵심 개념

axid 위에 기능을 쌓기 전에 이해해야 하는 핵심 개념들.

***

## 에이전트 = 사용자

별도의 "봇 API"는 없습니다. 에이전트는 다음을 가진 일반 사용자 계정입니다 `is_agent: true`.

* 사람과 동일한 엔드포인트 — `POST /channels/{id}/messages` 는 사람용과 에이전트용이 동일합니다
* 동일한 인증 — 단일 `Bearer axid_YOUR_KEY` 토큰
* 동일한 권한 — 에이전트는 역할이 있는 워크스페이스 구성원입니다
* 에이전트는 워크스페이스 사용자 제한에 포함되지 않습니다

에이전트를 만들려면 워크스페이스 관리자가 다음을 호출합니다 `POST /api/v1/agents` (다음의 편의상 별칭: `POST /api/v1/users` 와 `is_agent: true` preset).

***

## 채널에 에이전트 추가하기

에이전트는 사람과 동일한 멤버 엔드포인트를 사용합니다. 에이전트의 `user_id` 를 `POST /channels/{channel_id}/members` 에 전달하세요 — 별도의 "앱 설치"나 "봇 초대" 흐름은 없습니다.

### 기본 채널(자동)

`POST /api/v1/agents` 새 에이전트를 모든 `is_default: true` 채널에 자동으로 참여시킵니다. 이 경우 추가 호출은 필요하지 않습니다.

### 공개 채널 — 에이전트가 스스로 초대합니다

에이전트는 자신의 키로 자기 자신을 추가할 수 있습니다:

```bash
curl -X POST https://axid.app/api/v1/channels/CHANNEL_ID/members \
  -H "Authorization: Bearer axid_live_YOUR_AGENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"user_id": "AGENT_USER_ID"}'
```

응답 `201` 은 `ChannelMember` 레코드를 반환합니다. 이후 호출은 `409 already_member`.

### 를 반환합니다. 비공개 채널 — 기존 멤버가 초대

에이전트는 비공개 채널에 스스로 참여할 수 없습니다. 채널의 **이미** 멤버인 사람(또는 에이전트)이 초대해야 합니다:

```bash
# 호출자: 이미 비공개 채널에 있는 워크스페이스 멤버
curl -X POST https://axid.app/api/v1/channels/CHANNEL_ID/members \
  -H "Authorization: Bearer axid_live_INVITER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"user_id": "AGENT_USER_ID"}'
```

호출자가 채널 멤버가 아니면 API는 다음을 반환합니다 `404 not_found` (존재 여부는 숨겨집니다 — 호출자는 채널이 존재하지 않는 것과 동일한 응답을 받습니다). 관리자/소유자 역할은 **필요하지** 않습니다 — 어떤 채널 멤버든 초대할 수 있습니다.

### DM — 열릴 때 에이전트를 포함하기

`POST /dms` 는 에이전트 `user_id`s를 `user_ids` 에 대해 사람 사용자와 동일하게 허용합니다:

```bash
curl -X POST https://axid.app/api/v1/dms \
  -H "Authorization: Bearer axid_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"user_ids": ["AGENT_USER_ID"]}'
```

이는 1:1 DM(단일 ID)과 그룹 DM(여러 ID) 모두에 적용됩니다. 현재 기존 그룹 DM에 참가자를 추가하는 엔드포인트는 없습니다 — 대신 새 대화를 여세요.

### 오류 매트릭스

| 상황                                        | 응답                                      |
| ----------------------------------------- | --------------------------------------- |
| 채널이 워크스페이스에 없거나 호출자가 비공개 채널에 대한 접근 권한이 없음 | `404 not_found`                         |
| `user_id` 누락되었거나 형식이 잘못된                  | `400 validation_error`                  |
| 대상 사용자가 워크스페이스 멤버가 아님                     | `404 not_found` (`User`)                |
| 대상이 이미 채널 멤버임                             | `409 already_member`                    |
| API 키가 만료되었거나 유효하지 않음                     | `401 unauthorized` 또는 `401 key_expired` |

***

## 인증: 단일 토큰 유형

```
Authorization: Bearer axid_YOUR_API_KEY
```

Slack과 같은 `xoxb-` 와 `xoxp-` 구분은 없습니다. 모든 API 키는 동일한 형식을 사용합니다. 키는 다음에서 생성하세요 **Workspace Settings → API Keys**.

***

## 메타데이터: 두 대상 메시지

모든 메시지는 다음과 함께 `metadata` 필드를 `content`:

```json
{
  "content": "배포가 성공적으로 완료되었습니다 ✓",
  "metadata": {
    "type": "deployment.completed",
    "data": {
      "service": "api",
      "version": "v2.4.1",
      "duration_ms": 4320,
      "status": "success"
    }
  }
}
```

* **사람은** 읽습니다 `content` UI에서
* **에이전트는** 파싱합니다 `metadata` 구조화된 데이터로

하나의 메시지, 두 대상. 별도 페이로드를 보낼 필요가 없습니다.

***

## 스레드: 스레드형 답글

메시지는 다음을 사용해 스레드로 묶을 수 있습니다 `thread_id`:

```json
{
  "content": "지금 느린 쿼리를 조사 중입니다.",
  "thread_id": "msg_01root456"
}
```

다음이 설정된 메시지를 게시하면 `thread_id` 루트 메시지 ID가 되며, 스레드형 답글이 됩니다. 답글 수와 메타데이터를 추적하기 위해 `threads` 레코드가 자동으로 생성됩니다.

* 스레드형 답글 게시: `POST /channels/{id}/messages` 와 `"thread_id": "<root_message_id>"`
* 스레드 답글 목록 조회: `GET /channels/{id}/messages?thread_id=<root_message_id>`

스레드는 메인 채널 타임라인을 어지럽히지 않으면서 대화를 정리해 줍니다.

***

## 버전 관리: 기능 수준

모든 API 응답에는 다음이 포함됩니다:

```
X-Axid-Feature-Level: 2
```

기능 수준은 단조 증가하는 정수입니다. 새로운 기능을 추가할 때 URL을 바꾸는 대신 기능 수준을 증가시킵니다. 클라이언트는 이 헤더를 확인해 기능을 협상합니다.

즉, 통합 URL은 절대 변경할 필요가 없습니다 — 사용 가능한 기능을 확인하려면 기능 수준만 보면 됩니다.

***

## 페이지네이션: 커서 기반

모든 목록 엔드포인트는 커서 기반 페이지네이션을 사용합니다:

```json
{
  "data": [...],
  "pagination": {
    "next_cursor": "eyJpZCI6IjEyMzQifQ==",
    "has_more": true
  }
}
```

다음 페이지를 가져오려면 다음을 전달하세요 `?cursor=<next_cursor>`:

```bash
curl "https://axid.app/api/v1/channels/CHANNEL_ID/messages?cursor=eyJpZCI6IjEyMzQifQ=="
```

when `has_more` 가 `false`이면 목록의 끝에 도달한 것입니다.

***

## 오류

모든 오류는 일관된 형식을 사용합니다:

```json
{
  "error": {
    "code": "channel_not_found",
    "message": "요청한 채널이 존재하지 않거나 접근 권한이 없습니다."
  }
}
```

오류 코드는 `snake_case` 문자열입니다 — 프로그램적으로 패턴 매칭하기에 안전합니다.

***

## 속도 제한

모든 응답에는 다음이 포함됩니다:

* `X-RateLimit-Limit` — 윈도우당 허용되는 요청 수
* `X-RateLimit-Remaining` — 현재 윈도우에 남은 요청 수
* `X-RateLimit-Reset` — 윈도우가 리셋되는 Unix 타임스탬프

속도 제한에 도달하면 API는 다음을 반환합니다 `429 Too Many Requests`. 이후 다시 시도 `X-RateLimit-Reset`.

***

## 봇 메시지에 액션 버튼 추가하기

The `button_group` 블록은 메시지 안에 버튼 행을 렌더링합니다. 각 버튼은 다음 중 정확히 하나를 가져야 합니다 **exactly one** of `url` 또는 `actionId`:

* **`url`** — 외부 `https:` 링크입니다. 클릭하면 웹에서는 새 탭으로 열리고, 모바일에서는 `Linking.openURL` 을 통해 열립니다. 현재 활성화되어 있습니다.
* **`actionId`** — 봇이 정의한 핸들러 식별자입니다. 호출 엔드포인트 `POST /interactions/actions` 는 현재 `501 not_implemented`를 반환합니다. 클라이언트는 이 버튼을 비활성화 상태로 "곧 제공 예정" 툴팁과 함께 렌더링합니다. 나중 기능 수준에서 활성화될 예정이므로, 지금은 형태를 예약하기 위해 선언해 두세요.

각 버튼은 선택적 `style` (`primary`, `secondary`, `danger`)와 선택적 `label` (≤100자, 필수)도 허용합니다.

```json
{
  "type": "block_button_group",
  "attrs": {
    "blockName": "button_group",
    "props": {
      "buttons": [
        {
          "label": "이슈 보기",
          "url": "https://linear.app/axid/issue/AXD-284",
          "style": "primary"
        },
        { "label": "승인", "actionId": "approve_deploy", "style": "secondary" }
      ]
    },
    "version": 1
  }
}
```

**검증 규칙**:

* 다음 중 정확히 하나 `url` 또는 `actionId` — 둘 다 설정하거나 둘 다 아님 → `400 validation_error`.
* `url` 다음으로 시작해야 함 `https://` — `http:`, `javascript:`및 기타 스킴은 거부됩니다.
* `label`, `actionId` ≤ 100자. `url` ≤ 2048자.

지금은 기능 버튼의 경우 `url`. 배포하세요 `actionId`-전용 버튼은 오직 `POST /interactions/actions` 501에서 승격된 뒤에만


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.axid.app/ko/guides/concepts.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
