@sogni-ai/sogni-protocol 1.0.0-alpha.4 → 1.0.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/package.json +1 -1
- package/schemas/agent/intent-input.schema.json +128 -0
- package/schemas/agent/turn-analysis.schema.json +75 -0
- package/schemas/artifacts/artifact-graph.schema.json +42 -0
- package/schemas/artifacts/artifact-node.schema.json +137 -0
- package/schemas/billing/spend-gate.schema.json +130 -0
- package/schemas/billing/workflow-authorization.schema.json +83 -0
- package/schemas/events/run-event.schema.json +111 -0
- package/schemas/tools/tool-metadata.schema.json +78 -0
package/README.md
CHANGED
|
@@ -78,3 +78,12 @@ Tool prompt prose lives in `prompts/tools/*.json`. Each file is one [`PromptCont
|
|
|
78
78
|
## Editing schemas
|
|
79
79
|
|
|
80
80
|
The JSON Schema files under `schemas/` are the authoritative wire-spec shape. Any change here is a protocol bump (minor or major depending on compatibility). Consumers regenerate their language-specific types via their codegen step.
|
|
81
|
+
|
|
82
|
+
## v2 contract docs
|
|
83
|
+
|
|
84
|
+
This branch carries the additive schemas for the Sogni Platform v2 execution architecture. Two markdown documents under [`docs/`](./docs/) describe the new surface for downstream consumers:
|
|
85
|
+
|
|
86
|
+
- [`docs/v2-changes-summary.md`](./docs/v2-changes-summary.md) — concise map of the 8 new schemas (IntentInput, TurnAnalysis, ToolMetadata, ArtifactNode, ArtifactGraph, SpendGate, WorkflowAuthorization, RunEvent) and per-consumer impact.
|
|
87
|
+
- [`docs/v2-consumer-contract.md`](./docs/v2-consumer-contract.md) — full integration contract for native `sogni` (Mac/iOS via SogniKit codegen) and `sogni-creative-agent-skill`. Covers transport choice, classifier/regex replacement plan, artifact-graph projection, tool-surface budget, preserved public API params, and the workflow charging model.
|
|
88
|
+
|
|
89
|
+
v2 does not implement migration in the native or skill repos; their teams own implementation timing against this contract.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sogni-ai/sogni-protocol",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.5",
|
|
4
4
|
"description": "Language-neutral protocol artifacts for the Sogni ecosystem: tool schemas, prompts, OpenAI tool manifests, and enums. Consumed by every Sogni SDK (TypeScript, Swift, and future Python/Kotlin/Rust SDKs) so contracts stay in lockstep across languages.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sogni",
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://schemas.sogni.ai/creative-agent/2026-05-20.1/agent/intent-input.schema.json",
|
|
4
|
+
"title": "L1 IntentClassifier input packet",
|
|
5
|
+
"schemaVersion": "2026-05-20.1",
|
|
6
|
+
"description": "Compact context packet handed to the L1 IntentClassifier at the start of every user turn. Qwen3 256k context window comfortably holds 16-reference-image generations and multi-segment storyboard frames; the runtime never silently drops artifacts. Trim only when measured budget pressure forces it. This contract is built deterministically by the host (browser or cloud runner) from explicit runtime state; it never re-derives semantics from transcript regex.",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"currentMessage": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Raw user message text for this turn. Verbatim; sanitization belongs to boundary code, not this contract."
|
|
13
|
+
},
|
|
14
|
+
"currentMessageDetails": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"additionalProperties": false,
|
|
17
|
+
"description": "Optional structured form of the user's latest message. Producers MAY emit either currentMessage or this; consumers MUST handle BOTH. `text` is required so consumers can always derive a string-level view.",
|
|
18
|
+
"properties": {
|
|
19
|
+
"id": { "type": "string" },
|
|
20
|
+
"role": { "type": "string", "enum": ["user", "system"] },
|
|
21
|
+
"text": { "type": "string" },
|
|
22
|
+
"createdAt": { "type": "string", "format": "date-time" },
|
|
23
|
+
"localeHint": { "type": "string" }
|
|
24
|
+
},
|
|
25
|
+
"required": ["text"]
|
|
26
|
+
},
|
|
27
|
+
"runtimeFlags": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"additionalProperties": false,
|
|
30
|
+
"description": "Optional runtime feature flags the planner reads to decide tool surface and confirmation policy.",
|
|
31
|
+
"properties": {
|
|
32
|
+
"surface": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"enum": ["browser", "hosted_chat", "durable_chat", "workflow", "native", "skill"],
|
|
35
|
+
"description": "Originating producer surface."
|
|
36
|
+
},
|
|
37
|
+
"allowPaidTools": { "type": "boolean" },
|
|
38
|
+
"allowMutatingTools": { "type": "boolean" },
|
|
39
|
+
"durableRequired": { "type": "boolean" }
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"activeState": {
|
|
43
|
+
"type": "object",
|
|
44
|
+
"additionalProperties": false,
|
|
45
|
+
"description": "Currently-resolved focus state owned by the runtime (artifact graph + workflow runner). Populated from explicit runtime references — never from prose extraction.",
|
|
46
|
+
"properties": {
|
|
47
|
+
"activeArtifactId": { "type": "string" },
|
|
48
|
+
"activeArtifactType": {
|
|
49
|
+
"type": "string",
|
|
50
|
+
"enum": ["image", "video", "audio", "text", "workflow", "collection"]
|
|
51
|
+
},
|
|
52
|
+
"pendingAction": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"description": "Opaque reference to a runtime-tracked pending action (e.g. proposed plan awaiting selection). Shape is owned by the runtime, not this schema.",
|
|
55
|
+
"additionalProperties": true
|
|
56
|
+
},
|
|
57
|
+
"awaitingConfirmation": { "type": "boolean" },
|
|
58
|
+
"lastToolResult": {
|
|
59
|
+
"type": "object",
|
|
60
|
+
"additionalProperties": false,
|
|
61
|
+
"properties": {
|
|
62
|
+
"toolName": { "type": "string" },
|
|
63
|
+
"toolCallId": { "type": "string" },
|
|
64
|
+
"status": { "type": "string" }
|
|
65
|
+
},
|
|
66
|
+
"required": ["toolName", "toolCallId", "status"]
|
|
67
|
+
},
|
|
68
|
+
"activeWorkflowRunId": { "type": "string" }
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"artifactState": {
|
|
72
|
+
"type": "object",
|
|
73
|
+
"additionalProperties": false,
|
|
74
|
+
"description": "Stable artifact identifiers owned by the ArtifactGraph. Qwen3 256k context window comfortably holds 16-reference-image generations and multi-segment storyboard frames; the runtime never silently drops artifacts. Trim only when measured budget pressure forces it.",
|
|
75
|
+
"properties": {
|
|
76
|
+
"selectedArtifactIds": {
|
|
77
|
+
"type": "array",
|
|
78
|
+
"description": "Artifacts the user or planner has explicitly focused (e.g. multi-select for batch edit).",
|
|
79
|
+
"items": { "type": "string" }
|
|
80
|
+
},
|
|
81
|
+
"artifactIds": {
|
|
82
|
+
"type": "array",
|
|
83
|
+
"description": "Full conversation artifact id list. UNBOUNDED by default. Qwen3 256k context window comfortably holds 16-reference-image generations and multi-segment storyboard frames; the runtime never silently drops artifacts. Trim only when measured budget pressure forces it.",
|
|
84
|
+
"items": { "type": "string" }
|
|
85
|
+
},
|
|
86
|
+
"lastGeneratedArtifactId": { "type": "string" },
|
|
87
|
+
"lastEditedArtifactId": { "type": "string" }
|
|
88
|
+
},
|
|
89
|
+
"required": ["selectedArtifactIds", "artifactIds"]
|
|
90
|
+
},
|
|
91
|
+
"recentTurns": {
|
|
92
|
+
"type": "array",
|
|
93
|
+
"description": "Recent transcript window. UNBOUNDED by default. Qwen3 256k context window comfortably holds 16-reference-image generations and multi-segment storyboard frames; the runtime never silently drops artifacts. Trim only when measured budget pressure forces it. Sliding-window trimming from contextWindow.ts only fires after measured token budget pressure, and writes the trimmed prefix into conversationSummary.",
|
|
94
|
+
"items": {
|
|
95
|
+
"type": "object",
|
|
96
|
+
"additionalProperties": false,
|
|
97
|
+
"properties": {
|
|
98
|
+
"role": { "type": "string", "enum": ["user", "assistant", "tool", "system"] },
|
|
99
|
+
"content": { "type": "string" },
|
|
100
|
+
"sequence": { "type": "integer", "minimum": 0 }
|
|
101
|
+
},
|
|
102
|
+
"required": ["role", "content", "sequence"]
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"conversationSummary": {
|
|
106
|
+
"type": "string",
|
|
107
|
+
"description": "Rolling summary of trimmed prefix. Empty string until the first measured-budget-pressure trim event."
|
|
108
|
+
},
|
|
109
|
+
"userPreferences": {
|
|
110
|
+
"type": "object",
|
|
111
|
+
"description": "Free-form preference payload (e.g. preferred model tier, default aspect ratio). Deliberate exception: additionalProperties is true here, mirroring the data/metadata pattern in other contracts, because preferences evolve faster than the schema.",
|
|
112
|
+
"additionalProperties": true
|
|
113
|
+
},
|
|
114
|
+
"availableCapabilitiesSummary": {
|
|
115
|
+
"type": "array",
|
|
116
|
+
"description": "Short human-readable capability strings the planner can quote when answering capability questions without invoking any tool.",
|
|
117
|
+
"items": { "type": "string" }
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"required": [
|
|
121
|
+
"currentMessage",
|
|
122
|
+
"activeState",
|
|
123
|
+
"artifactState",
|
|
124
|
+
"recentTurns",
|
|
125
|
+
"conversationSummary",
|
|
126
|
+
"availableCapabilitiesSummary"
|
|
127
|
+
]
|
|
128
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://schemas.sogni.ai/creative-agent/2026-05-20.1/agent/turn-analysis.schema.json",
|
|
4
|
+
"title": "L1 IntentClassifier output",
|
|
5
|
+
"schemaVersion": "2026-05-20.1",
|
|
6
|
+
"description": "Structured output of the L1 IntentClassifier. Produced by an LLM-backed classifier, a typed planner, runtime state inspection, the artifact graph, or an explicit user signal — never by regex. Per the Codex reconciliation in v2 plan §1.A, the legacy SignalSource value 'regex' is intentionally absent from SignalProvenance; regex is demoted to bounded fact extraction (dimensions, durations, file types) which does not produce semantic intent.",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"$defs": {
|
|
10
|
+
"SignalProvenance": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Which layer authored this TurnAnalysis. The value 'regex' is intentionally absent — regex extracts bounded facts only and never decides intent, tool surface, or routing.",
|
|
13
|
+
"enum": [
|
|
14
|
+
"classifier",
|
|
15
|
+
"planner",
|
|
16
|
+
"runtime_state",
|
|
17
|
+
"artifact_graph",
|
|
18
|
+
"user_explicit"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"properties": {
|
|
23
|
+
"domain": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"enum": ["chat", "image", "video", "audio", "analysis", "workflow", "memory", "settings", "unknown"]
|
|
26
|
+
},
|
|
27
|
+
"intent": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"enum": ["generate", "edit", "analyze", "transform", "question", "capability", "continue", "reference", "configure", "clarify", "unknown"]
|
|
30
|
+
},
|
|
31
|
+
"executionMode": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"enum": ["none", "tool", "multi_tool", "workflow"]
|
|
34
|
+
},
|
|
35
|
+
"userWantsExecution": { "type": "boolean" },
|
|
36
|
+
"isCapabilityQuestion": { "type": "boolean" },
|
|
37
|
+
"isFutureInstruction": { "type": "boolean" },
|
|
38
|
+
"isReferenceOnly": { "type": "boolean" },
|
|
39
|
+
"needsPriorContext": { "type": "boolean" },
|
|
40
|
+
"needsClarification": { "type": "boolean" },
|
|
41
|
+
"referencedArtifacts": {
|
|
42
|
+
"type": "array",
|
|
43
|
+
"items": { "type": "string" },
|
|
44
|
+
"description": "Artifact ids the classifier resolved from the user's message via the artifact graph (positional references like 'the second image' resolve to stable ids before this list is emitted)."
|
|
45
|
+
},
|
|
46
|
+
"requiredCapabilities": {
|
|
47
|
+
"type": "array",
|
|
48
|
+
"items": { "type": "string" },
|
|
49
|
+
"description": "Free-form capability tags the planner must satisfy (e.g. 'image_generation', 'video_stitch')."
|
|
50
|
+
},
|
|
51
|
+
"confidence": {
|
|
52
|
+
"type": "number",
|
|
53
|
+
"minimum": 0,
|
|
54
|
+
"maximum": 1
|
|
55
|
+
},
|
|
56
|
+
"provenance": {
|
|
57
|
+
"$ref": "#/$defs/SignalProvenance"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"required": [
|
|
61
|
+
"domain",
|
|
62
|
+
"intent",
|
|
63
|
+
"executionMode",
|
|
64
|
+
"userWantsExecution",
|
|
65
|
+
"isCapabilityQuestion",
|
|
66
|
+
"isFutureInstruction",
|
|
67
|
+
"isReferenceOnly",
|
|
68
|
+
"needsPriorContext",
|
|
69
|
+
"referencedArtifacts",
|
|
70
|
+
"requiredCapabilities",
|
|
71
|
+
"needsClarification",
|
|
72
|
+
"confidence",
|
|
73
|
+
"provenance"
|
|
74
|
+
]
|
|
75
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://schemas.sogni.ai/creative-agent/2026-05-20.1/artifacts/artifact-graph.schema.json",
|
|
4
|
+
"title": "Artifact graph serialization",
|
|
5
|
+
"schemaVersion": "2026-05-20.1",
|
|
6
|
+
"description": "Durable serialization of the in-memory ArtifactGraph. The same shape mirrors into ChatRunRecord.artifacts[] and WorkflowRunRecord.artifacts[] so cloud and hosted runners can reconstitute the graph on resume. The runtime Map<string, ArtifactNode> serializes as a positional nodes[] array; artifactId uniqueness is a runtime invariant, not expressible cheaply in JSON Schema.",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"nodes": {
|
|
11
|
+
"type": "array",
|
|
12
|
+
"description": "All artifact nodes in the graph. Uniqueness on artifactId is enforced by the runtime, not the schema.",
|
|
13
|
+
"items": {
|
|
14
|
+
"$ref": "./artifact-node.schema.json"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"selectedId": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"description": "Optional currently-selected artifact id. When present, MUST match an artifactId in nodes."
|
|
20
|
+
},
|
|
21
|
+
"compatibilityProjections": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"additionalProperties": false,
|
|
24
|
+
"description": "Read-only legacy projections derived from nodes[]. Populated during the Phase 1-4 transition so existing chat-side code that still reads positional URL arrays keeps working. Deleted after plan Phase 5.",
|
|
25
|
+
"properties": {
|
|
26
|
+
"resultUrls": {
|
|
27
|
+
"type": "array",
|
|
28
|
+
"items": { "type": "string" }
|
|
29
|
+
},
|
|
30
|
+
"videoResultUrls": {
|
|
31
|
+
"type": "array",
|
|
32
|
+
"items": { "type": "string" }
|
|
33
|
+
},
|
|
34
|
+
"audioResultUrls": {
|
|
35
|
+
"type": "array",
|
|
36
|
+
"items": { "type": "string" }
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"required": ["nodes"]
|
|
42
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://schemas.sogni.ai/creative-agent/2026-05-20.1/artifacts/artifact-node.schema.json",
|
|
4
|
+
"title": "Artifact graph node",
|
|
5
|
+
"schemaVersion": "2026-05-20.1",
|
|
6
|
+
"description": "One node in the v2 ArtifactGraph. ArtifactNode replaces positional URL arrays (resultUrls / videoResultUrls / audioResultUrls) deleted in plan Phase 5. Every tool result auto-registers one node. Lineage edges resolve continuation ('use the second image', 'make it cinematic') without transcript scraping. Per-model token shape lives in modelRefs (gpt-image-2 'Image 1', seedance-2 '@Image1', ltx-2.3 'context_image_0').",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"$defs": {
|
|
10
|
+
"ArtifactEdge": {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"additionalProperties": false,
|
|
13
|
+
"description": "Typed lineage edge from this artifact to one of its parents.",
|
|
14
|
+
"properties": {
|
|
15
|
+
"parentId": { "type": "string" },
|
|
16
|
+
"relation": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"enum": [
|
|
19
|
+
"derived_from",
|
|
20
|
+
"edited_from",
|
|
21
|
+
"styled_from",
|
|
22
|
+
"animated_from",
|
|
23
|
+
"stitched_from",
|
|
24
|
+
"extended_from",
|
|
25
|
+
"segmented_from",
|
|
26
|
+
"reference_for"
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"required": ["parentId", "relation"]
|
|
31
|
+
},
|
|
32
|
+
"ArtifactVersion": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"additionalProperties": false,
|
|
35
|
+
"description": "One version of an artifact. Retries, refinements, and user-driven redos all append a version rather than mutating an existing one.",
|
|
36
|
+
"properties": {
|
|
37
|
+
"versionId": { "type": "string" },
|
|
38
|
+
"uri": { "type": "string" },
|
|
39
|
+
"createdAt": { "type": "string", "format": "date-time" },
|
|
40
|
+
"reason": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"enum": ["initial", "retry", "refinement", "audit_repair", "user_redo"]
|
|
43
|
+
},
|
|
44
|
+
"jobId": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"description": "Optional sogni-socket job id that produced this version."
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"required": ["versionId", "createdAt", "reason"]
|
|
50
|
+
},
|
|
51
|
+
"ArtifactSource": {
|
|
52
|
+
"oneOf": [
|
|
53
|
+
{
|
|
54
|
+
"type": "object",
|
|
55
|
+
"additionalProperties": false,
|
|
56
|
+
"properties": {
|
|
57
|
+
"type": { "const": "upload" },
|
|
58
|
+
"uploadId": { "type": "string" }
|
|
59
|
+
},
|
|
60
|
+
"required": ["type", "uploadId"]
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"type": "object",
|
|
64
|
+
"additionalProperties": false,
|
|
65
|
+
"properties": {
|
|
66
|
+
"type": { "const": "tool_result" },
|
|
67
|
+
"runId": { "type": "string" },
|
|
68
|
+
"toolCallId": { "type": "string" }
|
|
69
|
+
},
|
|
70
|
+
"required": ["type", "toolCallId"]
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"type": "object",
|
|
74
|
+
"additionalProperties": false,
|
|
75
|
+
"properties": {
|
|
76
|
+
"type": { "const": "workflow_stage" },
|
|
77
|
+
"workflowRunId": { "type": "string" },
|
|
78
|
+
"stageId": { "type": "string" },
|
|
79
|
+
"itemId": { "type": "string" }
|
|
80
|
+
},
|
|
81
|
+
"required": ["type", "workflowRunId", "stageId"]
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"properties": {
|
|
87
|
+
"artifactId": {
|
|
88
|
+
"type": "string",
|
|
89
|
+
"pattern": "^art_(?:[0-9A-Z]{26}|[0-9a-fA-F]{32}|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
|
|
90
|
+
"description": "Stable artifact id. ULID form (`art_` + 26-char Crockford base32 body) is RECOMMENDED for new ids — use `generateUlidArtifactId()` from `@sogni-ai/sogni-intelligence-client/artifacts`. Two legacy forms remain accepted so existing in-wild ids stay valid: `art_` + 32 hex chars (UUID with hyphens stripped, the historical `createArtifactNode` output) and `art_` + canonical UUID with hyphens. Read-side validators must keep accepting all three; write-side code SHOULD enforce ULID via `preferUlid()`."
|
|
91
|
+
},
|
|
92
|
+
"kind": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"enum": ["image", "video", "audio", "text", "workflow", "collection"]
|
|
95
|
+
},
|
|
96
|
+
"uri": {
|
|
97
|
+
"type": "string",
|
|
98
|
+
"description": "Canonical resolvable URI for the current version (mirrors versions[last].uri for convenience)."
|
|
99
|
+
},
|
|
100
|
+
"mimeType": { "type": "string" },
|
|
101
|
+
"userLabel": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"description": "Friendly label the user (or the system on the user's behalf) chose. Optional; planner falls back to artifactId + kind."
|
|
104
|
+
},
|
|
105
|
+
"modelRefs": {
|
|
106
|
+
"type": "object",
|
|
107
|
+
"additionalProperties": { "type": "string" },
|
|
108
|
+
"description": "Per-model formatter mapping. Keys are model ids; values are the token that model expects in prompts. Examples: gpt-image-2 -> 'Image 1', seedance-2 -> '@Image1', ltx-2.3 -> 'context_image_0'. Use the asset-reference helpers in @sogni/creative-agent rather than hand-formatting."
|
|
109
|
+
},
|
|
110
|
+
"source": { "$ref": "#/$defs/ArtifactSource" },
|
|
111
|
+
"parents": {
|
|
112
|
+
"type": "array",
|
|
113
|
+
"items": { "$ref": "#/$defs/ArtifactEdge" }
|
|
114
|
+
},
|
|
115
|
+
"versions": {
|
|
116
|
+
"type": "array",
|
|
117
|
+
"minItems": 1,
|
|
118
|
+
"items": { "$ref": "#/$defs/ArtifactVersion" }
|
|
119
|
+
},
|
|
120
|
+
"metadata": {
|
|
121
|
+
"type": "object",
|
|
122
|
+
"additionalProperties": true,
|
|
123
|
+
"description": "Free-form artifact metadata (width/height, durationSeconds, seed, prompt summary, etc.). Boundary code populates known fields; consumers must not assume any specific field is present."
|
|
124
|
+
},
|
|
125
|
+
"createdAt": { "type": "string", "format": "date-time" }
|
|
126
|
+
},
|
|
127
|
+
"required": [
|
|
128
|
+
"artifactId",
|
|
129
|
+
"kind",
|
|
130
|
+
"modelRefs",
|
|
131
|
+
"source",
|
|
132
|
+
"parents",
|
|
133
|
+
"versions",
|
|
134
|
+
"metadata",
|
|
135
|
+
"createdAt"
|
|
136
|
+
]
|
|
137
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://schemas.sogni.ai/creative-agent/2026-05-20.1/billing/spend-gate.schema.json",
|
|
4
|
+
"title": "Spend gate request and state",
|
|
5
|
+
"schemaVersion": "2026-05-20.1",
|
|
6
|
+
"description": "Single shared spend-approval state machine for both atomic tool calls (scope='tool_call') and workflow authorizations (scope='workflow_run'). One envelope, one state enum, one transition log. Per-job settlement remains on the sogni-socket project+N path — this gate authorizes spend, it does not move funds.",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"$defs": {
|
|
10
|
+
"SpendGateState": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Canonical lifecycle states for a spend gate. 'not_required' = free / no-cost tool. 'preview_required' = estimate must be shown to the user. 'waiting_for_user' = awaiting confirm or cancel. 'confirmed' = user accepted; runner may dispatch. 'cancelled' = user declined. 'insufficient_credit' = wallet balance below estimate. 'safety_review_required' = blocked pending human or automated safety review. 'failed' = unrecoverable error in the gate itself.",
|
|
13
|
+
"enum": [
|
|
14
|
+
"not_required",
|
|
15
|
+
"preview_required",
|
|
16
|
+
"waiting_for_user",
|
|
17
|
+
"confirmed",
|
|
18
|
+
"cancelled",
|
|
19
|
+
"insufficient_credit",
|
|
20
|
+
"safety_review_required",
|
|
21
|
+
"failed"
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
"SpendGateDecision": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"enum": ["confirm", "cancel"]
|
|
27
|
+
},
|
|
28
|
+
"SpendEstimateLineItem": {
|
|
29
|
+
"type": "object",
|
|
30
|
+
"additionalProperties": false,
|
|
31
|
+
"description": "One row of the spend estimate breakdown. Sum of (units * model price) across line items yields the totalEstimatedCapacityUnits.",
|
|
32
|
+
"properties": {
|
|
33
|
+
"model": { "type": "string" },
|
|
34
|
+
"units": { "type": "number", "minimum": 0 },
|
|
35
|
+
"tokenType": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
"enum": ["spark", "sogni"]
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"required": ["model", "units", "tokenType"]
|
|
41
|
+
},
|
|
42
|
+
"PendingToolCall": {
|
|
43
|
+
"type": "object",
|
|
44
|
+
"additionalProperties": false,
|
|
45
|
+
"description": "Minimal reference to a tool call this gate covers (when scope='tool_call' the array has one entry; when scope='workflow_run' the gate authorizes the umbrella and pendingToolCalls may be empty).",
|
|
46
|
+
"properties": {
|
|
47
|
+
"toolCallId": { "type": "string" },
|
|
48
|
+
"toolName": { "type": "string" }
|
|
49
|
+
},
|
|
50
|
+
"required": ["toolCallId", "toolName"]
|
|
51
|
+
},
|
|
52
|
+
"PendingWorkflowPlan": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"additionalProperties": false,
|
|
55
|
+
"description": "Reference to the workflow run this gate authorizes (only meaningful when scope='workflow_run').",
|
|
56
|
+
"properties": {
|
|
57
|
+
"workflowRunId": { "type": "string" },
|
|
58
|
+
"templateId": { "type": "string" }
|
|
59
|
+
},
|
|
60
|
+
"required": ["workflowRunId", "templateId"]
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"oneOf": [
|
|
64
|
+
{
|
|
65
|
+
"type": "object",
|
|
66
|
+
"additionalProperties": false,
|
|
67
|
+
"properties": {
|
|
68
|
+
"gateId": { "type": "string" },
|
|
69
|
+
"runId": { "type": "string" },
|
|
70
|
+
"scope": { "const": "tool_call" },
|
|
71
|
+
"toolCallId": { "type": "string" },
|
|
72
|
+
"pendingToolCalls": {
|
|
73
|
+
"type": "array",
|
|
74
|
+
"items": { "$ref": "#/$defs/PendingToolCall" }
|
|
75
|
+
},
|
|
76
|
+
"estimate": {
|
|
77
|
+
"type": "object",
|
|
78
|
+
"additionalProperties": false,
|
|
79
|
+
"properties": {
|
|
80
|
+
"totalEstimatedCapacityUnits": { "type": "number", "minimum": 0 },
|
|
81
|
+
"breakdown": {
|
|
82
|
+
"type": "array",
|
|
83
|
+
"minItems": 1,
|
|
84
|
+
"items": { "$ref": "#/$defs/SpendEstimateLineItem" }
|
|
85
|
+
},
|
|
86
|
+
"maxAcceptableUnits": { "type": "number", "minimum": 0 }
|
|
87
|
+
},
|
|
88
|
+
"required": ["totalEstimatedCapacityUnits", "breakdown"]
|
|
89
|
+
},
|
|
90
|
+
"state": { "$ref": "#/$defs/SpendGateState" },
|
|
91
|
+
"reason": { "type": "string" },
|
|
92
|
+
"decision": { "$ref": "#/$defs/SpendGateDecision" },
|
|
93
|
+
"decidedAt": { "type": "string", "format": "date-time" },
|
|
94
|
+
"lastTransitionAt": { "type": "string", "format": "date-time" }
|
|
95
|
+
},
|
|
96
|
+
"required": ["gateId", "scope", "toolCallId", "estimate", "state", "lastTransitionAt"]
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"type": "object",
|
|
100
|
+
"additionalProperties": false,
|
|
101
|
+
"properties": {
|
|
102
|
+
"gateId": { "type": "string" },
|
|
103
|
+
"runId": { "type": "string" },
|
|
104
|
+
"scope": { "const": "workflow_run" },
|
|
105
|
+
"workflowRunId": { "type": "string" },
|
|
106
|
+
"pendingWorkflowPlan": { "$ref": "#/$defs/PendingWorkflowPlan" },
|
|
107
|
+
"estimate": {
|
|
108
|
+
"type": "object",
|
|
109
|
+
"additionalProperties": false,
|
|
110
|
+
"properties": {
|
|
111
|
+
"totalEstimatedCapacityUnits": { "type": "number", "minimum": 0 },
|
|
112
|
+
"breakdown": {
|
|
113
|
+
"type": "array",
|
|
114
|
+
"minItems": 1,
|
|
115
|
+
"items": { "$ref": "#/$defs/SpendEstimateLineItem" }
|
|
116
|
+
},
|
|
117
|
+
"maxAcceptableUnits": { "type": "number", "minimum": 0 }
|
|
118
|
+
},
|
|
119
|
+
"required": ["totalEstimatedCapacityUnits", "breakdown"]
|
|
120
|
+
},
|
|
121
|
+
"state": { "$ref": "#/$defs/SpendGateState" },
|
|
122
|
+
"reason": { "type": "string" },
|
|
123
|
+
"decision": { "$ref": "#/$defs/SpendGateDecision" },
|
|
124
|
+
"decidedAt": { "type": "string", "format": "date-time" },
|
|
125
|
+
"lastTransitionAt": { "type": "string", "format": "date-time" }
|
|
126
|
+
},
|
|
127
|
+
"required": ["gateId", "scope", "workflowRunId", "estimate", "state", "lastTransitionAt"]
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://schemas.sogni.ai/creative-agent/2026-05-20.1/billing/workflow-authorization.schema.json",
|
|
4
|
+
"title": "Workflow authorization ticket",
|
|
5
|
+
"schemaVersion": "2026-05-20.1",
|
|
6
|
+
"description": "Umbrella authorization ticket recorded once at workflow run start. The executor consults it before dispatching each stage and pauses for re-authorization if cumulative settled + reserved + next-estimate would exceed authorizedCapacityUnits. Per-job settlement continues through the existing sogni-socket 'project + N identical jobs' path; the workflow layer is an authorization umbrella, not a new transaction ledger.",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"$defs": {
|
|
10
|
+
"StageSettlementStatus": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"enum": ["pending", "in_flight", "settled", "failed", "cancelled"]
|
|
13
|
+
},
|
|
14
|
+
"StageSettlement": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"additionalProperties": false,
|
|
17
|
+
"description": "Per-stage ledger row. estimatedUnits comes from the WorkflowCostPreview; settledUnits is filled in as the sogni-socket worker(s) for this stage finish.",
|
|
18
|
+
"properties": {
|
|
19
|
+
"stageId": { "type": "string" },
|
|
20
|
+
"projectId": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "sogni-socket project id. Null until dispatched."
|
|
23
|
+
},
|
|
24
|
+
"jobIds": {
|
|
25
|
+
"type": "array",
|
|
26
|
+
"description": "sogni-socket job ids. Empty until dispatched. May have multiple entries for fan-out stages.",
|
|
27
|
+
"items": { "type": "string" }
|
|
28
|
+
},
|
|
29
|
+
"estimatedUnits": { "type": "number", "minimum": 0 },
|
|
30
|
+
"settledUnits": {
|
|
31
|
+
"type": "number",
|
|
32
|
+
"minimum": 0,
|
|
33
|
+
"description": "Cumulative settled units for this stage. Null until at least one worker completes."
|
|
34
|
+
},
|
|
35
|
+
"status": { "$ref": "#/$defs/StageSettlementStatus" }
|
|
36
|
+
},
|
|
37
|
+
"required": ["stageId", "estimatedUnits", "status"]
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"properties": {
|
|
41
|
+
"workflowRunId": { "type": "string" },
|
|
42
|
+
"authorizedCapacityUnits": {
|
|
43
|
+
"type": "number",
|
|
44
|
+
"minimum": 0,
|
|
45
|
+
"description": "Umbrella cap. Per-job settlements stay within this; if next dispatch would exceed by more than the documented drift tolerance the run pauses for re-authorization."
|
|
46
|
+
},
|
|
47
|
+
"tokenType": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
"enum": ["spark", "sogni"]
|
|
50
|
+
},
|
|
51
|
+
"authorizedAt": { "type": "string", "format": "date-time" },
|
|
52
|
+
"expiresAt": {
|
|
53
|
+
"type": "string",
|
|
54
|
+
"format": "date-time",
|
|
55
|
+
"description": "Past expiry, the run pauses with cost_approval_required for re-authorization. Template declares an expected duration; expiry is duration + retry grace."
|
|
56
|
+
},
|
|
57
|
+
"cumulativeSettledUnits": {
|
|
58
|
+
"type": "number",
|
|
59
|
+
"minimum": 0,
|
|
60
|
+
"description": "Sum of stageSettlements[].settledUnits to date."
|
|
61
|
+
},
|
|
62
|
+
"cumulativeReservedUnits": {
|
|
63
|
+
"type": "number",
|
|
64
|
+
"minimum": 0,
|
|
65
|
+
"description": "Estimated units for in-flight jobs not yet settled."
|
|
66
|
+
},
|
|
67
|
+
"stageSettlements": {
|
|
68
|
+
"type": "array",
|
|
69
|
+
"description": "Per-stage ledger. May be empty pre-dispatch; populated as the executor dispatches each stage.",
|
|
70
|
+
"items": { "$ref": "#/$defs/StageSettlement" }
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"required": [
|
|
74
|
+
"workflowRunId",
|
|
75
|
+
"authorizedCapacityUnits",
|
|
76
|
+
"tokenType",
|
|
77
|
+
"authorizedAt",
|
|
78
|
+
"expiresAt",
|
|
79
|
+
"cumulativeSettledUnits",
|
|
80
|
+
"cumulativeReservedUnits",
|
|
81
|
+
"stageSettlements"
|
|
82
|
+
]
|
|
83
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://schemas.sogni.ai/creative-agent/2026-05-20.1/events/run-event.schema.json",
|
|
4
|
+
"title": "Unified run event",
|
|
5
|
+
"schemaVersion": "2026-05-20.1",
|
|
6
|
+
"description": "Single event vocabulary across chat runs and workflow runs. Both persist into the shared `runs` substrate (plan §13.5) and differ only by the runKind discriminator. SSE replay key is (runId, sequence). idempotencyKey covers reentrant transitions such as cost confirmation. Per-event-type payload shapes are deliberately not enforced at this layer — payload shapes are documented per type and tightened in a Phase 1 follow-up to avoid an enormous union in this round.",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"$defs": {
|
|
10
|
+
"RunEventType": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "All event types. Clusters: lifecycle (run_queued, run_started, run_completed, run_partial_failure, run_failed, run_cancelled), LLM (llm_round_started, llm_token, llm_round_completed), tools (tool_call_proposed, tool_call_dispatched, tool_call_progress, tool_call_resolved), artifacts (artifact_created, artifact_updated, artifact_referenced), waiting (run_waiting_for_user), spend (spend_preview_emitted, spend_confirmed, spend_cancelled, spend_insufficient), audit (audit_evaluated, repair_requested), workflow-stage (stage_started, stage_completed, stage_failed, stage_waiting_for_user).",
|
|
13
|
+
"enum": [
|
|
14
|
+
"run_queued",
|
|
15
|
+
"run_started",
|
|
16
|
+
"run_completed",
|
|
17
|
+
"run_partial_failure",
|
|
18
|
+
"run_failed",
|
|
19
|
+
"run_cancelled",
|
|
20
|
+
"llm_round_started",
|
|
21
|
+
"llm_token",
|
|
22
|
+
"llm_round_completed",
|
|
23
|
+
"tool_call_proposed",
|
|
24
|
+
"tool_call_dispatched",
|
|
25
|
+
"tool_call_progress",
|
|
26
|
+
"tool_call_resolved",
|
|
27
|
+
"artifact_created",
|
|
28
|
+
"artifact_updated",
|
|
29
|
+
"artifact_referenced",
|
|
30
|
+
"run_waiting_for_user",
|
|
31
|
+
"spend_preview_emitted",
|
|
32
|
+
"spend_confirmed",
|
|
33
|
+
"spend_cancelled",
|
|
34
|
+
"spend_insufficient",
|
|
35
|
+
"audit_evaluated",
|
|
36
|
+
"repair_requested",
|
|
37
|
+
"stage_started",
|
|
38
|
+
"stage_completed",
|
|
39
|
+
"stage_failed",
|
|
40
|
+
"stage_waiting_for_user"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"RunStatus": {
|
|
44
|
+
"type": "string",
|
|
45
|
+
"description": "Unified status enum across chat and workflow runs.",
|
|
46
|
+
"enum": [
|
|
47
|
+
"queued",
|
|
48
|
+
"running",
|
|
49
|
+
"completed",
|
|
50
|
+
"partial_failure",
|
|
51
|
+
"waiting_for_user",
|
|
52
|
+
"failed",
|
|
53
|
+
"cancelled"
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
"WaitingReason": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"description": "Why a run paused. Carried inside the payload of a run_waiting_for_user event (and stage_waiting_for_user where applicable).",
|
|
59
|
+
"enum": [
|
|
60
|
+
"ask_clarifying_question",
|
|
61
|
+
"select_media_required",
|
|
62
|
+
"cost_approval_required",
|
|
63
|
+
"safety_review_required",
|
|
64
|
+
"workflow_user_input_required",
|
|
65
|
+
"insufficient_credit",
|
|
66
|
+
"other"
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"properties": {
|
|
71
|
+
"runId": { "type": "string" },
|
|
72
|
+
"runKind": {
|
|
73
|
+
"type": "string",
|
|
74
|
+
"enum": ["chat", "workflow"],
|
|
75
|
+
"description": "Substrate discriminator (plan §13.5). chat and workflow runs share persistence, lease, heartbeat, event log, waiting semantics, cancellation, cost confirmation, and resume."
|
|
76
|
+
},
|
|
77
|
+
"sequence": {
|
|
78
|
+
"type": "integer",
|
|
79
|
+
"minimum": 0,
|
|
80
|
+
"description": "Strictly increasing per runId. SSE replay key is (runId, sequence)."
|
|
81
|
+
},
|
|
82
|
+
"type": { "$ref": "#/$defs/RunEventType" },
|
|
83
|
+
"status": { "$ref": "#/$defs/RunStatus" },
|
|
84
|
+
"payload": {
|
|
85
|
+
"type": "object",
|
|
86
|
+
"additionalProperties": true,
|
|
87
|
+
"description": "Per-type payload. Documented shapes: run_waiting_for_user -> { reason: WaitingReason, ... }; tool_call_proposed/_dispatched/_progress/_resolved -> { toolCallId, toolName, ... }; artifact_* -> { artifactId, ... }; spend_* -> { gateId, scope, ... }; audit_evaluated -> { toolCallId, passed, ... }; repair_requested -> { toolCallId, reason, retryCount }; stage_* -> { stageId, ... }. Schema-level enforcement of these shapes is intentionally deferred to Phase 1 to avoid an unwieldy union here."
|
|
88
|
+
},
|
|
89
|
+
"createdAt": { "type": "string", "format": "date-time" },
|
|
90
|
+
"resumable": {
|
|
91
|
+
"type": "boolean",
|
|
92
|
+
"description": "True when the run is in a state the client can resume from (typically paired with run_waiting_for_user)."
|
|
93
|
+
},
|
|
94
|
+
"terminal": {
|
|
95
|
+
"type": "boolean",
|
|
96
|
+
"description": "True for the final event of a run (run_completed / run_failed / run_cancelled / run_partial_failure)."
|
|
97
|
+
},
|
|
98
|
+
"idempotencyKey": {
|
|
99
|
+
"type": "string",
|
|
100
|
+
"description": "Stable key for reentrant transitions (e.g. POST /confirm-cost). Re-submitting the same key MUST be a no-op."
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
"required": [
|
|
104
|
+
"runId",
|
|
105
|
+
"runKind",
|
|
106
|
+
"sequence",
|
|
107
|
+
"type",
|
|
108
|
+
"payload",
|
|
109
|
+
"createdAt"
|
|
110
|
+
]
|
|
111
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://schemas.sogni.ai/creative-agent/2026-05-20.1/tools/tool-metadata.schema.json",
|
|
4
|
+
"title": "Tool catalog metadata",
|
|
5
|
+
"schemaVersion": "2026-05-20.1",
|
|
6
|
+
"description": "Metadata that accompanies each tool definition in the v2 catalog. Drives tool surfacing decisions (which family/execution mode is visible this turn), spend gating (costClass + requiresConfirmation), retry behavior (retrySafety), and durable-run observability (mutatesData, producesArtifacts). Input/output schema refs point at sogni-protocol argument and result contracts so the validator and the planner share one source of truth.",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"name": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Canonical tool name (snake_case, matches the OpenAI-format tool definition exposed to the LLM)."
|
|
13
|
+
},
|
|
14
|
+
"family": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"enum": ["creative", "composition", "artifact", "memory", "settings", "analysis", "control"],
|
|
17
|
+
"description": "Coarse grouping used by the planner to pick a minimal visible tool subset."
|
|
18
|
+
},
|
|
19
|
+
"executionMode": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"enum": ["hosted", "client", "app", "workflow", "internal"],
|
|
22
|
+
"description": "Where the tool runs. 'hosted' = sogni-api durable runner. 'client' = browser tool dispatch. 'app' = native shell. 'workflow' = synthetic tool that creates a WorkflowRun. 'internal' = runtime-only (e.g. L1 hidden resolver) — never surfaced to the LLM directly."
|
|
23
|
+
},
|
|
24
|
+
"inputSchemaRef": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"description": "URI or repo-relative path. MUST resolve to a sogni-protocol tool argument JSON Schema (e.g. schemas/tools/generate_image.schema.json)."
|
|
27
|
+
},
|
|
28
|
+
"outputSchemaRef": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "URI or repo-relative path. MUST resolve to a sogni-protocol tool result envelope schema."
|
|
31
|
+
},
|
|
32
|
+
"costClass": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"enum": ["free", "low", "medium", "high", "variable"],
|
|
35
|
+
"description": "Indicative cost tier. Concrete unit estimates live on the SpendGate request, not here."
|
|
36
|
+
},
|
|
37
|
+
"latencyClass": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"enum": ["inline", "interactive", "long_running"],
|
|
40
|
+
"description": "Indicative wall-clock tier. 'long_running' tools generally belong inside a Workflow Template, not a synchronous chat turn."
|
|
41
|
+
},
|
|
42
|
+
"mutatesData": {
|
|
43
|
+
"type": "boolean",
|
|
44
|
+
"description": "True when the tool changes persisted user state (e.g. manage_memory write, settings update)."
|
|
45
|
+
},
|
|
46
|
+
"producesArtifacts": {
|
|
47
|
+
"type": "boolean",
|
|
48
|
+
"description": "True when the tool emits one or more ArtifactNodes that must be registered in the ArtifactGraph."
|
|
49
|
+
},
|
|
50
|
+
"requiresConfirmation": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"enum": ["never", "paid", "destructive", "always"],
|
|
53
|
+
"description": "Confirmation policy. 'paid' defers to SpendGate. 'destructive' requires an explicit user yes regardless of cost. 'always' is reserved for atomic operations with no other gate."
|
|
54
|
+
},
|
|
55
|
+
"retrySafety": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"enum": ["idempotent", "dedupe_key_required", "not_safe"],
|
|
58
|
+
"description": "Whether the runner may retry the tool call on a transient failure. 'dedupe_key_required' tools must be called with a stable dedupe token (e.g. sogni-socket project id)."
|
|
59
|
+
},
|
|
60
|
+
"hiddenFromModel": {
|
|
61
|
+
"type": "boolean",
|
|
62
|
+
"description": "Optional. L1 hidden context tools (resolve_*, inspect_*) set this true so the runner can call them directly without surfacing them to the LLM."
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"required": [
|
|
66
|
+
"name",
|
|
67
|
+
"family",
|
|
68
|
+
"executionMode",
|
|
69
|
+
"inputSchemaRef",
|
|
70
|
+
"outputSchemaRef",
|
|
71
|
+
"costClass",
|
|
72
|
+
"latencyClass",
|
|
73
|
+
"mutatesData",
|
|
74
|
+
"producesArtifacts",
|
|
75
|
+
"requiresConfirmation",
|
|
76
|
+
"retrySafety"
|
|
77
|
+
]
|
|
78
|
+
}
|