# Document & Table Nodes

> Applies to: ChengOS v0.2.0+ ｜ Last verified: 2026-09-25 ｜ Source: `crates/cheng-nodes/src/nodes/builtin/document`, `crates/cheng-nodes/src/nodes/builtin/table`

Structured content, in two shapes. Documents are block-based: `document/ops_hub` dispatches by
operation the way the file hub does, while the individual nodes create, query, and update blocks
explicitly. Tables are record-based, with a query node, a node that applies record operations, and a
node that renders a table into LLM context. The `format_for_llm` and `build_llm_context` nodes exist
because raw document or table JSON is a poor prompt — they produce the bounded, readable form a model
should actually see. Shadow-session internals are hidden and driven by the hub.

## Document Operations Hub — `document/ops_hub`

Document operations hub node: control Agent document capabilities with toggle switches

### Inputs

| Field | Type | Required | Default | Description |
|---|---|:-:|---|---|
| `operation` | string | — | `""` | Operation type |
| `document_id` | string | — | — | Document ID (common to most operations) |
| `config` | object (port) | — | — | Unified config object (can input JSON text directly). Connection port, not a form field. Control: `text` |
| `workspace_id` | string | — | — | Workspace ID (used by create operation, set by user on canvas) |
| `allow_query` | boolean | ✅ | `true` | Whether to allow querying documents (read-only). Control: `switch` |
| `allow_format` | boolean | ✅ | `true` | Whether to allow formatting documents (read-only). Control: `switch` |
| `allow_discovery` | boolean | ✅ | `true` | Whether to allow document discovery (list/search) (read-only). Control: `switch` |
| `allow_diff` | boolean | ✅ | `true` | Whether to allow diff preview of proposed edits (read-only). Control: `switch` |
| `allow_update` | boolean | ✅ | `false` | Whether to allow updating document blocks (medium side-effect). Control: `switch` |
| `allow_batch` | boolean | ✅ | `false` | Whether to allow batch document operations (mixed side-effect). Control: `switch` |
| `allow_create` | boolean | ✅ | `false` | Whether to allow creating new documents (medium side-effect). Control: `switch` |
| `allow_duplicate` | boolean | ✅ | `false` | Whether to allow duplicating documents (medium side-effect). Control: `switch` |
| `allow_import` | boolean | ✅ | `false` | Whether to allow importing documents from text (medium side-effect). Control: `switch` |
| `allow_delete_document` | boolean | ✅ | `false` | Whether to allow hard-deleting documents (high risk). Control: `switch` |
| `allow_rollback` | boolean | ✅ | `false` | Whether to allow restoring/rolling back a document from a snapshot (high risk). Control: `switch` |

### Outputs

| Field | Type | Description |
|---|---|---|
| `operation` | string | Actual operation type executed |
| `requires_review` | boolean | Whether this operation staged a shadow that must be reviewed. |
| `shadow_id` | string | Shadow session ID, when a write operation is staged for review. |
| `document_id` | string | Document ID associated with the staged review. |
| `change_summary` | string | Summary lifted from shadow apply output for Agent final/review handling. |
| `error` | string | Error message (operation prohibited or execution failed) |
| `result` | any | Operation result (JSON-serialized sub-node output) |
| `preview_context` | string | Preview lifted from shadow apply output for Agent final/review handling. |

## Create Document — `document/create`

Create a new document in workspace, supports AgentContext pass-through

### Inputs

| Field | Type | Required | Default | Description |
|---|---|:-:|---|---|
| `context` | object (port) | — | `null` | AgentContext port. Connection port, not a form field. |
| `title` | string | — | `null` | Optional title for the document. |
| `initial_content` | string | — | `null` | Initial content for the first block (optional). |
| `block_type` | string | — | `paragraph` | Block type for initial content (default: paragraph). |
| `priority` | enum | — | `normal` | Initial block priority. Control: `select`. Options: `low`, `normal`, `medium`, `high`, `critical` |
| `tags` | string | — | `null` | Initial block tags (comma-separated) |

### Outputs

| Field | Type | Description |
|---|---|---|
| `context` | object (port) | AgentContext port. Connection port, not a form field. |
| `string` | string | Formatted success message with title and document_id |
| `document_id` | string | ID of the created document. |
| `title` | string | Title of the created document. |
| `root_block_id` | string | ID of the root block. |
| `success` | boolean | Whether creation was successful. |
| `error` | string | Error message if creation failed. |

## Query Document — `document/query`

Get document content, optionally return as block structure or Markdown format

### Inputs

| Field | Type | Required | Default | Description |
|---|---|:-:|---|---|
| `document_id` | string | ✅ | — | Select document to query (from current workspace). Control: `dynamic-select` |
| `include_content` | boolean | — | `true` | Whether to include full block content (default: true). |
| `as_markdown` | boolean | — | `false` | Optional: return content as markdown instead of blocks. |

### Outputs

| Field | Type | Description |
|---|---|---|
| `success` | boolean | Whether the query was successful. |
| `found` | boolean | Whether the document was found. |
| `document_id` | string | Document ID (if found). |
| `title` | string | Document title. |
| `blocks` | array&lt;object&gt; | All blocks in the document. |
| `markdown` | string | Full document content as markdown (if as_markdown=true). |
| `plain_text` | string | Plain text content. |
| `block_count` | integer | Number of blocks. |
| `character_count` | integer | Total character count. |
| `error` | string | Error message if query failed. |
| `content_type` | string | Content type (richtext/markdown). |
| `root_block_id` | string | Root block ID. |

## Update Document Block — `document/update_block`

Update content or type of a specific block in document, supports AgentContext pass-through

### Inputs

| Field | Type | Required | Default | Description |
|---|---|:-:|---|---|
| `context` | object (port) | — | `null` | AgentContext port. Connection port, not a form field. |
| `document_id` | string | ✅ | — | Select document to update. Control: `dynamic-select` |
| `block_id` | string | ✅ | — | ID of the block to update. |
| `content` | string | ✅ | — | New content for the block. |
| `block_type` | string | — | `null` | New block type (optional, keeps existing if not provided). |
| `language` | string | — | `null` | Language for code blocks (optional). |
| `priority` | enum | — | `null` | Block priority. Control: `select`. Options: `low`, `normal`, `medium`, `high`, `critical` |
| `tags` | string | — | `null` | Block tags (comma-separated) |

### Outputs

| Field | Type | Description |
|---|---|---|
| `context` | object (port) | AgentContext port. Connection port, not a form field. |
| `string` | string | Formatted success message with document_id and block_id |
| `success` | boolean | Whether the update was successful. |
| `block_id` | string | Updated block ID. |
| `block_type` | string | Updated block type. |
| `content` | string | Updated content. |
| `document_version` | integer | New document version after update. |
| `error` | string | Error message if update failed. |

## Extract Document Items — `document/extract_items`

Extract document block tags + lines into Loop-ready items

### Inputs

| Field | Type | Required | Default | Description |
|---|---|:-:|---|---|
| `document_id` | string | ✅ | — | Select a document, searchable by name. Control: `dynamic-select` |
| `extract_target` | enum | — | `tags` | Which payload to emit: tags, lines, pairs, objects, groups. Control: `select`. Options: `tags` (Just the tag list.), `lines` (Just the line list.), `pairs` (`{ tag, line }` pairs.), `objects` (Structured object whose keys are tags, values are selected lines.), `groups` (Full `{ tag, lines }` candidate pool.) |
| `combine_mode` | enum | — | `list` | Combination mode: list, sequential, random, selected, zip, cartesian. Control: `select`. Options: `list` (Simple flat list.), `sequential` (Iterate in document order (tags × lines, document-order interleaved).), `random` (One random pick per tag.), `selected` (Use `selection_map` to pick one line per tag.), `zip` (Align lines across tags by index.), `cartesian` (Cartesian product across tags.) |
| `tag_filter` | string | — | `null` | Filter tags (comma-separated, case-insensitive substring match) |
| `tag_policy` | enum | — | `first_tag` | How to handle blocks with multiple tags. Control: `select`. Options: `first_tag` (Use only the first tag of a block as its group label.), `all_tags` (The same block belongs to every tag it carries.) |
| `untagged_policy` | enum | — | `skip` | How to handle blocks without tags. Control: `select`. Options: `skip` (Skip blocks without tags (default).), `group` (Group untagged blocks under the synthetic tag `_untagged`.) |
| `selection_map` | object | — | `null` | User selection per tag (populated by popup widget). Control: `document-extract-selector`. Shown when `document_id` |
| `random_seed` | string | — | `null` | Optional seed for reproducible random selection |
| `max_items` | integer | — | `0` | Maximum number of items to emit (0 = unlimited). Control: `number` |
| `delimiter` | string | — | `, ` | Delimiter used to join item texts into formatted_text |
| `strict` | boolean | — | `false` | Error out when selection_map references missing lines. Control: `switch` |

### Outputs

| Field | Type | Description |
|---|---|---|
| `items` | any | Standard Loop items array |
| `formatted_text` | string | Items joined into a single string |
| `groups` | array&lt;object&gt; | Tag → candidate lines pool |
| `count` | integer | Items count. |
| `document_title` | string | Document title (if any). |
| `success` | boolean | Whether the node executed successfully. |
| `error` | string | Fatal error message (if any). |
| `warnings` | array&lt;string&gt; | Non-fatal warnings. |

## Format Document (LLM) — `document/format_for_llm`

Read and format document for LLM use, supports priority and tag filtering

### Inputs

| Field | Type | Required | Default | Description |
|---|---|:-:|---|---|
| `context` | object (port) | — | `null` | AgentContext port. Connection port, not a form field. |
| `document_id` | string | ✅ | — | Select a document to read, searchable by name. Control: `dynamic-select` |
| `priority_filter` | enum | — | `all` | Filter blocks by priority. Control: `select`. Options: `all` (所有优先级), `high_only` (仅高优先级（High + Critical）), `critical_only` (仅 Critical), `normal_and_above` (Normal 及以上（Normal + High + Critical）) |
| `tag_filter` | string | — | `null` | Filter by tags (comma-separated, e.g.: core concepts,API) |
| `sort_order` | enum | — | `original` | Block sort order. Control: `select`. Options: `original` (按文档原始顺序), `priority_desc` (按优先级降序（Critical -> High -> Normal -> Low）), `priority_asc` (按优先级升序（Low -> Normal -> High -> Critical）) |
| `output_format` | enum | — | `markdown` | Output format. Control: `select`. Options: `markdown` (Markdown 格式), `plain_text` (纯文本), `structured` (结构化（包含块信息）) |
| `include_metadata` | boolean | — | `true` | Whether to include block tags and priority info in output |
| `system_prompt` | string | — | `null` | Custom system prompt (optional). Control: `textarea` |
| `max_chars` | integer | — | `0` | Maximum character limit (0 means unlimited) |

### Outputs

| Field | Type | Description |
|---|---|---|
| `context` | object (port) | AgentContext port. Connection port, not a form field. |
| `formatted_content` | string | Formatted document content |
| `preview_content` | string | Preview-friendly document summary with title, character count, and content excerpt |
| `blocks` | array&lt;object&gt; | Structured block list |
| `title` | string | 文档标题 |
| `block_count` | integer | 处理的块数量 |
| `filtered_block_count` | integer | 过滤后的块数量 |
| `character_count` | integer | 总字符数 |
| `truncated` | boolean | 是否被截断 |
| `success` | boolean | 是否成功 |
| `error` | string | 错误信息 |

## Query Table — `table/query`

Get table data, including column definitions and records

### Inputs

| Field | Type | Required | Default | Description |
|---|---|:-:|---|---|
| `table_id` | string | ✅ | — | ID of the table to query. |
| `record_ids` | array | — | `null` | Optional list of specific record IDs to fetch. If not provided, fetches all records (paginated). |
| `include_schema` | boolean | — | `true` | Whether to include column definitions (default: true). |
| `page` | integer | — | `1` | Page number for pagination (1-based, default: 1). |
| `page_size` | integer | — | `100` | Number of records per page (default: 100, max: 1000). |

### Outputs

| Field | Type | Description |
|---|---|---|
| `success` | boolean | Whether the query was successful. |
| `found` | boolean | Whether the table was found. |
| `table` | object | Table metadata (if found). |
| `columns` | array&lt;object&gt; | Column definitions (if include_schema=true). |
| `records` | array&lt;object&gt; | Records data. |
| `total_records` | integer | Total number of records in the table. |
| `page` | integer | Current page number. |
| `total_pages` | integer | Total number of pages. |
| `error` | string | Error message if query failed. |
| `markdown` | string | Markdown formatted table (columns + records), suitable for preview node. |
| `agent_context` | object (port) | AgentContext port (can be directly connected to Agent node's context input). Connection port, not a form field. |

## Apply Table Operations — `table/apply_record_ops`

Batch apply table record insert, update, delete operations

### Inputs

| Field | Type | Required | Default | Description |
|---|---|:-:|---|---|
| `table_id` | string | ✅ | — | Table ID to apply operations to. |
| `operations` | array&lt;enum&gt; | ✅ | — | List of operations to apply. |
| `summary` | string | — | `null` | Optional summary of changes (for logging/audit). |

### Outputs

| Field | Type | Description |
|---|---|---|
| `success` | boolean | Whether all operations were successful. |
| `results` | array&lt;object&gt; | Results for each operation. |
| `summary` | string | Summary of changes. |
| `table_id` | string | Table ID. |
| `records_affected` | integer | Number of records affected. |
| `records_inserted` | integer | Number of records inserted. |
| `records_updated` | integer | Number of records updated. |
| `records_deleted` | integer | Number of records deleted. |
| `error` | string | Error message if the overall operation failed. |

## Build Table LLM Context — `table/build_llm_context`

Build context information for LLM table editing

### Inputs

| Field | Type | Required | Default | Description |
|---|---|:-:|---|---|
| `table_id` | string | ✅ | — | Table ID to build context for. |
| `selected_record_ids` | array | — | `null` | Optional list of selected record IDs. If provided, only these records will be included in the context. |
| `instruction` | string | ✅ | — | User's editing instruction/request. |
| `format` | string | — | `json` | Output format: "json", "markdown", or "csv". |
| `max_records` | integer | — | `100` | Maximum records to include in context (0 = unlimited). |

### Outputs

| Field | Type | Description |
|---|---|---|
| `success` | boolean | Whether context building was successful. |
| `table_id` | string | Table ID. |
| `table_name` | string | Table name. |
| `system_prompt` | string | System prompt for LLM. |
| `table_context` | string | Table context (formatted table data). |
| `user_prompt` | string | User instruction (formatted). |
| `tools_json` | string | Tool definitions JSON for LLM function calling. |
| `llm_context` | string | Integrated LLM context as JSON string. Connect this to ReAct agent's `task` input. |
| `agent_context` | object (port) | AgentContext port (can be directly connected to Agent node's context input). Connection port, not a form field. |
| `records_included` | integer | Number of records included. |
| `column_count` | integer | Number of columns. |
| `error` | string | Error message if building failed. |
| `warnings` | array&lt;string&gt; | Warnings generated during context building. |

## Next steps

- [Document Workspace](/docs/data-document-workspace)
- [Table Workspace](/docs/data-table-workspace)
- [Workspace Nodes](/docs/nodes-workspace)
