Content Node
A Content Node is the basic unit of data in PuppyOne.
What is a Content Node
Inside every PuppyOne Project is a content tree, much like a cloud file system. You can create folders, store JSON data, edit Markdown documents, and upload attachments, and AI agents can read and write those contents directly.
Unlike a traditional table-based model, the content tree supports both structured data and unstructured documents, with arbitrary nesting for greater flexibility.
Four node types
| Type | Description | Typical Use |
|---|---|---|
folder | A folder that can contain child nodes | Organizing directory structure |
json | A JSON file for structured data | Product data, configuration, API responses |
markdown | A Markdown file for rich text content | Docs, knowledge base articles, meeting notes |
file | A binary uploaded file | PDFs, images, attachments |
Tree structure
Content Nodes form a tree identified by path. Every node has a unique path within its project, just like in a file system:
/
├── docs/
│ ├── product-spec.md ← Markdown node
│ ├── api-reference.md ← Markdown node
│ └── changelog.json ← JSON node
├── data/
│ ├── products.json ← JSON node
│ ├── customers.json ← JSON node
│ └── attachments/
│ └── contract.pdf ← File node
└── README.md ← Markdown nodeYou can manage Content Nodes much like local files: create directories, move files, rename them, and delete them — all addressed by path.
Storage model
Content is stored in a Mut Merkle tree backed by S3, not in a PostgreSQL table. Each write creates a Mut commit that captures the full tree state, enabling:
- Immutable version history
- Efficient diffing between any two commits
- Atomic multi-file operations
- Rollback to any previous commit
The Merkle tree structure ensures data integrity and makes it possible to verify that content has not been tampered with.
Node properties
Each Content Node includes these core properties:
| Property | Description |
|---|---|
path | Full path within the project, such as data/products.json |
name | Node name, such as products.json |
type | Node type: folder, json, markdown, or file |
content | Node contents. JSON or Markdown text for supported types; empty for folders and files |
project_id | The Project this node belongs to |
Version history and audit
Every Content Node tracks changes automatically:
- Version history — Every write creates a new Mut commit. You can compare any two versions and roll back in one click.
- Audit logs — See who performed which action on which node, and when.
Access control
Content Nodes support fine-grained access control through FLS, or File Level Security:
- Authorize by path — Agents can only access approved paths (configured via
access_points.config.scope) - Authorize by operation — Restrict access to read-only or read/write
- Unauthorized paths are physically invisible to the agent
For example, a support agent may only be allowed to access products and faq, while everything under internal remains hidden.
Working with Content Nodes
Through the Dashboard
In a project's data view, click the create button to add a folder, JSON file, or Markdown file. Uploaded files can be dragged directly into the page.
Through the REST API
All content operations use the /api/v1/content/{project_id}/... endpoints with path-based addressing:
BASE_URL="https://api.puppyone.ai/api/v1/content/YOUR_PROJECT_ID"
TOKEN="YOUR_ACCESS_TOKEN"
# Create a folder
curl -X POST "$BASE_URL/mkdir" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"path": "docs"}'
# Write a JSON file
curl -X POST "$BASE_URL/write" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"path": "data/products.json",
"content": {"items": []},
"node_type": "json",
"message": "Create products file"
}'
# Read file content
curl "$BASE_URL/cat?path=data/products.json" \
-H "Authorization: Bearer $TOKEN"
# List directory
curl "$BASE_URL/ls?path=data" \
-H "Authorization: Bearer $TOKEN"Through external sync sources
Once you add external sources like Notion, GitHub, or Gmail as access points, synced data is automatically transformed into Content Nodes and stored in your project's file tree.
Best practices
- Organize by folder — Structure directories by business domain, such as
products,docs, andsupport - Use JSON for structured data and Markdown for documents — Pick the node type that best fits the content
- Use paths to separate permissions — Put content with different access needs into different directories
- Take advantage of version history — You can always roll back if a change goes wrong