---
title: "Giải thích Manifest"
description: "manifest.yaml là contract khai báo giữa app và SotaAgents: app là gì, đóng góp gì, backend ở đâu, native module nào được load và hỗ trợ platform version nào. Server luôn validat…"
url: "https://sotaagents.ai/vi/manual/developer-guide/manifest-explained"
generated_by: "sotaagents-ldp"
docs_index: "https://sotaagents.ai/manual/llms.txt"
locale: "vi"
---

# Giải thích Manifest

`manifest.yaml` là contract khai báo giữa app và SotaAgents: app là gì, đóng góp gì, backend ở đâu, native module nào được load và hỗ trợ platform version nào. Server luôn validate lại; manifest từ client không phải authority. Property lạ bị từ chối thẳng — chạy `sota manifest schema` để đọc đúng JSON Schema và `sota manifest explain contributes.tools` để giải thích một field.

Năm field gốc `manifestSchemaVersion`, `appId`, `version`, `publisher` và `contributes` là bắt buộc. Còn lại đều tùy chọn.

YAML

```
manifestSchemaVersion: 3
appId: my-first-project-demo
version: 1.0.0
displayName: "My First Project Demo"
description: "SotaAgent app."
publisher:
  id: local-dev
  displayName: "Local Dev"
  contact: dev@local-dev.example

contributes:
  skills:
    - name: example
      description: Example content-backed skill.
      appendsTo: system
      content: src/skills/example
      timeoutMs: 3000
      failure_mode: skip
  tools:
    - name: example
      description: Example tool that echoes its input and verified tenant context.
      route: POST /tools/example
      inputSchema: src/schemas/tool-input.schema.json
      outputSchema: src/schemas/tool-output.schema.json
      timeoutMs: 15000
      failure_mode: abort
  ui:
    - id: admin-screen
      kind: nativeModule
      surface: page
      slot: admin.workspace.tab
      sectionId: my-first-project-demo
      label: Admin screen
      route: /admin/*
      module:
        entry: dist/ui/app.js
        export: AdminScreen
        styles: dist/ui/app.css

service:
  baseUrl: https://my-first-project-demo.example.com
health:
  url: https://my-first-project-demo.example.com/health
  intervalSeconds: 60
platform: ^1.2.0
locales:
  default: en
  files:
    en: src/locales/en.json
```

- **Identity** ổn định; coi `appId` là public identifier vĩnh viễn.
- **Version** bất biến theo artifact; đổi bytes sau deploy phải tăng version.
- **Contributions** là toàn bộ surface nền tảng được phép expose.
- **Environment overlay** là override tùy chọn mang đúng tên `local`, `stg` hoặc `prod`. Root service là hosted default; `local` dành cho `sota dev`. Global `--origin` chọn deployment SotaAgents, còn `-e` ở từng command chọn profile/overlay tương ứng.

Mỗi native UI surface và public runtime API được hướng dẫn trên một trang riêng sau phần manifest này.

YAML

```
service:
  baseUrl: https://my-app.example.com
health:
  url: https://my-app.example.com/health
  intervalSeconds: 60

environments:
  local:
    service:
      baseUrl: http://127.0.0.1:8787
    health:
      url: http://127.0.0.1:8787/health
  stg:
    service:
      baseUrl: https://stg.my-app.example.com
  prod:
    service:
      baseUrl: https://my-app.example.com
```

> [!WARNING]
> environments.local
>
> Manifest gốc mô tả app deploy được. URL `127.0.0.1` trong block `service` gốc sẽ bị từ chối, và base URL deploy vẫn còn đuôi `.invalid` nghĩa là backend host thật chưa từng được cấu hình.

### Khai báo một tool

Tool là cách trợ lý chạm tới backend của bạn. Bạn khai báo nó một lần dưới `contributes.tools`; nền tảng suy ra mọi thứ còn lại từ khai báo đó — model được mời gọi gì, request route ra sao, authenticate thế nào, và được phép chạy bao lâu. Schema là schema đóng, nên một key không khai báo sẽ fail validation.

| Field | Bắt buộc | Quy tắc |
| --- | --- | --- |
| `name` | Có | Public identifier ổn định. Ký tự đầu viết thường, sau đó là chữ, số và gạch nối, có thể chia đoạn bằng dấu chấm (ví dụ `documents.query`); mỗi đoạn tối đa 64 ký tự. Giữ nguyên tên sau khi release — prompt, renderer và conversation đã lưu đều tham chiếu tới nó. |
| `description` | Có | Không được rỗng. Đây chính là đoạn text model đọc khi quyết định có gọi tool hay không, nên hãy nói rõ khi nào dùng, backend làm gì, trả về gì và có điều kiện tiên quyết nào. Đừng chỉ chép lại tên tool. |
| `route` | Có | `METHOD /path`, với method thuộc `GET`, `POST`, `PUT`, `PATCH`, `DELETE` và path bắt đầu bằng `/`. Path được resolve theo `service.baseUrl` của environment đang dùng và không được thoát khỏi origin đó. Hãy khai `POST`: đường gọi của trợ lý gửi arguments dưới dạng JSON body, và scaffold cùng mọi system app đều dùng `POST /tools/<name>`. |
| `inputSchema` | Có | Đường dẫn tới file JSON Schema nằm trong app, hoặc một schema object viết thẳng. Nên dùng `required` tường minh, `additionalProperties: false`, string/array có giới hạn, và enum cho các mode đã biết. |
| `outputSchema` | Có | Cùng dạng với input schema. Bắt buộc kể cả khi kết quả rất đơn giản — nó tài liệu hóa contract mà backend của bạn phải giữ. |
| `timeoutMs` | Không | Số nguyên dương, bị kẹp tối đa 30.000 ms khi build artifact. Hãy khai báo. Tool không khai báo sẽ không có ngân sách thời gian nào trên backend host, còn tunnel Development giới hạn ở mười phút. |
| `failure_mode` | Không | `abort` hoặc `skip`; tool mặc định là `abort`. Chọn `abort` khi lỗi phải được báo là lỗi; chỉ chọn `skip` khi contribution thực sự tùy chọn và trợ lý vẫn trả lời trung thực được nếu thiếu nó. Đừng che giấu một lệnh ghi thất bại hay một truy vấn quan trọng sau vẻ ngoài "vẫn ổn". |
| `searchHint` | Không | Từ khóa bổ sung giúp tìm ra tool. Không được rỗng. |
| `undoable` | Không | Boolean. Đánh dấu action có thể hoàn tác. |
| `configGate` | Không | Một app-config key. Tool chỉ được đưa ra khi config key đó tồn tại. |

File schema mà khai báo trỏ tới là JSON Schema bình thường. Compiler resolve và inline chúng vào artifact, nên file được tham chiếu phải tồn tại trước khi build hay deploy, kể cả khi route đó không được gọi lúc test local.

JSON

```
// src/schemas/tool-input.schema.json
{
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "message": {
      "type": "string",
      "minLength": 1,
      "maxLength": 4000,
      "description": "Message for the example tool to echo."
    }
  },
  "required": ["message"]
}
```

Khai báo bất kỳ tool nào cũng khiến `service` trở thành bắt buộc — nền tảng phải biết gửi request đi đâu. Tên tool phải duy nhất trong một manifest, và UI contribution có `surface: tool-view` phải liệt kê trong `toolNames` những tên thực sự tồn tại trong `contributes.tools`; validator từ chối renderer gắn với tool bạn chưa khai báo. Hai app đã cài không được cùng giành một tên tool cho renderer — app vào sau mất các tên bị tranh chấp.

Về những gì nền tảng làm tiếp với khai báo này — tên model nhìn thấy, signed request, contract của response — xem _Triết lý kiến trúc_.

![Trang detail của Staging app hiển thị surface overview](/manual/assets/developer/app-surface-overview.webp)
_Exact environment chỉ expose tools, skills, UI slots, prompts và grants đã khai báo trong artifact đó._
