| slug | HttpAPI |
|---|---|
| title | HTTP API |
| description | Ultron REST API reference |
Ultron exposes a REST API on FastAPI, default base http://0.0.0.0:9999.
uvicorn ultron.server:app --host 0.0.0.0 --port 9999- Responses: JSON
- Background: Memory decay runs on
decay_interval_hours; ifasync_embedding=true, an embedding worker shares the sameUltroninstance as HTTP
GET /
Response:
{
"status": "ok",
"service": "ultron",
"version": "1.0.0",
"architecture": "collective-intelligence"
}GET /stats
Aggregates skill storage, skill categories, embedding service, and memory store.
Example shape:
{
"storage": {
"total_skills": 56,
"archived_skills": 2,
"total_size_bytes": 1048576,
"total_size_mb": 1.0,
"skills_dir": "/path/to/skills",
"archive_dir": "/path/to/archive"
},
"categories": {
"total_skills": 56,
"total_categories": 120,
"categories_with_skills": 45,
"dimension_stats": {},
"top_categories": [{"name": "ai-llms", "count": 8}]
},
"embedding": {
"backend": "dashscope",
"model_name": "text-embedding-v4",
"dimension": 1024,
"is_available": true,
"has_dashscope": true,
"has_numpy": true,
"request_timeout_seconds": 600
},
"memory": {
"total": 1234,
"by_tier": {"hot": 40, "warm": 500, "cold": 694},
"by_type": {"pattern": 800, "error": 400},
"by_status": {"active": 1200}
}
}POST /memory/upload
Body:
| Field | Type | Required | Description |
|---|---|---|---|
content |
string | yes | Memory body |
context |
string | no | Scenario |
resolution |
string | no | Fix or playbook |
tags |
string[] | no | Tags |
Response:
{
"success": true,
"data": {
"id": "mem-xxx",
"memory_type": "error",
"tier": "warm",
"hit_count": 1,
"status": "active"
}
}POST /memory/search
Body:
| Field | Type | Required | Description |
|---|---|---|---|
query |
string | yes | Natural language |
tier |
string | no | hot / warm / cold / all; omit or null = all |
limit |
int | no | Max rows; omit → ULTRON_MEMORY_SEARCH_LIMIT (default 10) |
detail_level |
string | no | l0 or l1 (default l0). Truncates or clears body fields; l0 is summary-first; l1 keeps more context |
Response:
{
"success": true,
"count": 5,
"data": [
{
"id": "mem-xxx",
"memory_type": "error",
"content": "",
"context": "",
"resolution": "",
"summary_l0": "Handling missing pandas in Python",
"overview_l1": "",
"tier": "warm",
"similarity_score": 0.8765,
"tier_boosted_score": 1.0518
}
]
}POST /memory/details
{
"memory_ids": ["mem-001", "mem-002", "mem-003"]
}
Returns readable MemoryRecord fields (full content / context / resolution, tags, summaries, timestamps).
{
"success": true,
"count": 2,
"data": [
{
"id": "mem-001",
"memory_type": "error",
"content": "full text ...",
"context": "",
"resolution": "",
"tier": "warm",
"hit_count": 3,
"summary_l0": "",
"overview_l1": ""
}
]
}GET /memory/stats
{
"success": true,
"data": {
"total": 1234,
"by_tier": { "hot": 40, "warm": 500, "cold": 694 },
"by_type": { "pattern": 800 },
"by_status": { "active": 1100 }
}
}POST /ingest
{
"paths": ["/path/to/file.txt", "/path/to/sessions/"]
}
success:truewhendata.successful > 0data: Raw smart-ingestion result (paths processed, counts, etc.; exact keys depend on runtime)
POST /ingest/text
{
"text": "raw text..."
}
success: from the ingest resultsuccessflagdata: Details dict fromingest_text
GET /skills
{
"success": true,
"count": 2,
"data": [
{ "slug": "my-skill", "version": "1.0.0", "path": "/abs/path/to/my-skill-1.0.0" }
]
}POST /skills/search
{
"query": "how to fix Python import errors",
"limit": 3
}
limitomitted →ULTRON_SKILL_SEARCH_LIMIT(default 5)
{
"success": true,
"count": 2,
"data": [
{
"slug": "fix-imports",
"version": "1.0.0",
"name": "Fix Imports",
"description": "...",
"categories": ["coding-agents-ides"],
"similarity_score": 0.82,
"combined_score": 0.91,
"source": "internal",
"full_name": null
},
{
"slug": "catalog-skill-example",
"version": "1.0.0",
"name": "Catalog Skill Example",
"description": "...",
"categories": ["coding-agents-ides"],
"similarity_score": 0.78,
"combined_score": 0.85,
"source": "catalog",
"full_name": "@ns/catalog-skill-example"
}
]
}POST /skills/upload
{
"paths": ["/path/to/skill-dir", "/path/to/skills-folder"]
}
Directory rules: if the path contains SKILL.md at top level, it is one skill; if not, scan one level of subfolders that contain SKILL.md.
Response:
{
"success": true,
"data": {
"total": 2,
"successful": 2,
"results": [
{"path": "/path/to/skill-dir", "success": true, "slug": "my-skill", "version": "1.0.0", "name": "My Skill"},
{"path": "/path/to/skills-folder/sub-skill", "success": true, "slug": "sub-skill", "version": "1.0.0", "name": "Sub Skill"}
]
}
}success: true when successful > 0.
POST /skills/install
Installs into a target directory. Resolves internal slug first; otherwise modelscope skill add for catalog skills.
Body:
{
"full_name": "@ns/name",
"target_dir": "~/.nanobot/workspace/skills"
}| Field | Type | Required | Description |
|---|---|---|---|
full_name |
string | yes | Catalog name like @ns/name, or internal slug |
target_dir |
string | yes | Destination directory |
Response:
{
"success": true,
"full_name": "@ns/name",
"source": "internal",
"installed_path": "~/.nanobot/workspace/skills/@ns/name"
}source:"internal"or"catalog"
GET /harness/agents?user_id=u1
{
"success": true,
"count": 2,
"data": [...]
}DELETE /harness/agents
Body:
| Field | Type | Required |
|---|---|---|
user_id |
string | yes |
agent_id |
string | yes |
Deletes the agent’s profile and share tokens.
POST /harness/sync/up
Body:
| Field | Type | Required | Description |
|---|---|---|---|
user_id |
string | yes | User id |
agent_id |
string | yes | Device id |
product |
string | no | Claw product (default nanobot) |
resources |
object | yes | Map of relative path → file text |
Response:
{
"success": true,
"data": {
"user_id": "u1",
"agent_id": "d1",
"revision": 1,
"resources": {"SOUL.md": "..."},
"product": "nanobot",
"updated_at": "2026-04-06T12:00:00"
}
}POST /harness/sync/down
Body:
| Field | Type | Required |
|---|---|---|
user_id |
string | yes |
agent_id |
string | yes |
404 if no profile exists.
GET /harness/profile?user_id=u1&agent_id=d1
POST /harness/share
Body:
| Field | Type | Required | Description |
|---|---|---|---|
user_id |
string | yes | Owner user |
agent_id |
string | yes | Owner device |
visibility |
string | no | link / public / private (default link) |
Response:
{
"success": true,
"data": {
"token": "abc123...",
"source_user_id": "u1",
"source_agent_id": "d1",
"visibility": "link",
"snapshot": {...},
"created_at": "2026-04-06T12:00:00"
}
}POST /harness/share/import
Body:
| Field | Type | Required |
|---|---|---|
token |
string | yes |
target_user_id |
string | yes |
target_agent_id |
string | yes |
Imports the snapshot as the target user’s profile.
GET /harness/shares?user_id=u1
DELETE /harness/share
Body:
| Field | Type | Required |
|---|---|---|
token |
string | yes |
| Code | Meaning |
|---|---|
| 200 | Success |
| 400 | Bad request |
| 403 | Forbidden |
| 404 | Not found (e.g. skill missing) |
| 422 | Validation error (FastAPI) |
| 500 | Server error |
Each request gets a trace_id:
- Response header:
X-Trace-Id: a1b2c3d4e5f6 - Correlate logs with this id
Default allow_origins=["*"]. Lock this down in production.