{
  "components": {
    "schemas": {
      "ChatCompletionRequest": {
        "additionalProperties": false,
        "description": "OpenAI POST /v1/chat/completions request.",
        "properties": {
          "allowed_tools": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional tool allowlist for this completion. Overrides project/env when set. Also accepted via X-Allowed-Tools header (comma-separated).",
            "title": "Allowed Tools"
          },
          "messages": {
            "description": "Conversation messages",
            "items": {
              "$ref": "#/components/schemas/ChatMessage"
            },
            "title": "Messages",
            "type": "array"
          },
          "model": {
            "default": "digigraph-rag",
            "description": "Model id (ignored; we use project config)",
            "title": "Model",
            "type": "string"
          },
          "openwebui_format": {
            "default": false,
            "description": "If true, format tool blocks for Open WebUI (<details>, summary + tables). Also enabled by X-Response-Format: openwebui. model=digigraph-rag alone does not enable this; opt out anytime via X-Suppress-Tool-Stream or X-Response-Format: plain|neutral|none|digichat.",
            "title": "Openwebui Format",
            "type": "boolean"
          },
          "require_tool_calls": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional per-request signal that this completion needs tool_choice='required'. Also accepted via X-Require-Tool-Calls header. Combined with project agents.require_tool_calls and env DIGI_REQUIRE_TOOL_CALLS as a FLOOR (any true value wins) — unlike allowed_tools, this can only raise the requirement, never lower one the deployment already mandates.",
            "title": "Require Tool Calls"
          },
          "session_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional conversation/session id. Isolates digistore and checkpoint state per conversation. Also set via X-Session-Id or X-Thread-Id header.",
            "title": "Session Id"
          },
          "stream": {
            "default": false,
            "description": "If true, return SSE stream",
            "title": "Stream",
            "type": "boolean"
          }
        },
        "required": [
          "messages"
        ],
        "title": "ChatCompletionRequest",
        "type": "object"
      },
      "ChatMessage": {
        "description": "OpenAI-style message.",
        "properties": {
          "content": {
            "default": "",
            "description": "Message content (string or OpenAI/AI SDK part list)",
            "title": "Content",
            "type": "string"
          },
          "role": {
            "description": "user, assistant, or system",
            "title": "Role",
            "type": "string"
          }
        },
        "required": [
          "role"
        ],
        "title": "ChatMessage",
        "type": "object"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "title": "HTTPValidationError",
        "type": "object"
      },
      "ResumeThreadRequest": {
        "additionalProperties": false,
        "description": "Body for POST /threads/{thread_id}/resume.",
        "properties": {
          "resume": {
            "anyOf": [
              {},
              {
                "type": "null"
              }
            ],
            "description": "Value passed to LangGraph Command(resume=...). Omit for a plain re-invoke.",
            "title": "Resume"
          }
        },
        "title": "ResumeThreadRequest",
        "type": "object"
      },
      "ValidationError": {
        "properties": {
          "ctx": {
            "title": "Context",
            "type": "object"
          },
          "input": {
            "title": "Input"
          },
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "title": "Location",
            "type": "array"
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        },
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError",
        "type": "object"
      },
      "WorkflowRequest": {
        "additionalProperties": false,
        "description": "Input for run_digigraph_workflow (e.g. user idea or backtest request).",
        "properties": {
          "allowed_tools": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional allowlist of orchestrator tool names. When set (including []), overrides project agents.allowed_tools and DIGI_ALLOWED_TOOLS. Omit to use those sources.",
            "title": "Allowed Tools"
          },
          "digi_bearer": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "digikey-issued JWT forwarded to digiquant/digisearch as Authorization Bearer.",
            "title": "Digi Bearer"
          },
          "digi_subject": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "JWT subject for checkpoint thread scoping and Store namespace keying. Client-writable on this model but never trusted as-is: server.py's _with_digi_request_context/_digi_fields_from_request unconditionally overwrite this field with the verified auth.subject when request auth carries a non-empty subject, and clear it to None otherwise (no auth at all, or an auth object with an empty subject claim) — a client-supplied value never reaches graph state or the Store namespace key unverified. See ARCHITECTURE.md §6.10.",
            "title": "Digi Subject"
          },
          "digi_trace_jti": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "JWT jti for audit (optional).",
            "title": "Digi Trace Jti"
          },
          "digi_trace_key_prefix": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "digikey key prefix for audit (optional).",
            "title": "Digi Trace Key Prefix"
          },
          "digi_trace_project_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Project id for audit (optional).",
            "title": "Digi Trace Project Id"
          },
          "digi_trace_tenant": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Tenant slug for audit (optional).",
            "title": "Digi Trace Tenant"
          },
          "digisearch_index": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-request digisearch index. Client-writable on this model but, when DIGI_TENANT_CORPUS_MAP is set, overwritten server-side from the authenticated tenant's map entry (headers/body cannot select another tenant's corpus). When the map is unset, X-Digi-Corpus-Index may set it.",
            "title": "digisearch index"
          },
          "evidence_tier_preference": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Preferred evidence_tier values (peer_reviewed, working_paper, …) added as a filter.",
            "title": "Evidence Tier Preference"
          },
          "prompt": {
            "description": "User idea, e.g. 'Build me a mean-reversion stat-arb on tech'",
            "title": "Prompt",
            "type": "string"
          },
          "request_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Correlates audit logs and outbound HTTP (X-Request-ID). Set from X-Request-ID on HTTP or generated for MCP.",
            "title": "Request Id"
          },
          "require_tool_calls": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional per-request signal that this workflow needs tool_choice='required'. Combined with project agents.require_tool_calls and env DIGI_REQUIRE_TOOL_CALLS as a FLOOR (any true value wins) — unlike allowed_tools, this can only raise the requirement, never lower one the deployment already mandates.",
            "title": "Require Tool Calls"
          },
          "research_filters": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional structured digisearch filters merged into every digisearch tool call.",
            "title": "Research Filters"
          },
          "research_system_prompt_override": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional research system prompt from DIGI_TENANT_CORPUS_MAP.",
            "title": "Research System Prompt Override"
          },
          "response_language": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-request response language code (X-Digi-Language). One of the curated codes in digigraph.languages.LANGUAGE_NAMES; unrecognized values are ignored.",
            "title": "Response Language"
          },
          "session_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional session for checkpointing (Phase 1)",
            "title": "Session Id"
          },
          "strategy_params": {
            "anyOf": [
              {
                "additionalProperties": {
                  "anyOf": [
                    {
                      "type": "number"
                    },
                    {
                      "type": "integer"
                    },
                    {
                      "type": "string"
                    }
                  ]
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional digiquant strategy parameters when skipping LLM extraction.",
            "title": "Strategy Params"
          },
          "trading_profile": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional digiclone profile dict (maps into optimization constraints in graph).",
            "title": "Trading Profile"
          },
          "vault_path_prefix": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-request digivault path prefix. Same trust rule as digisearch_index: map is authoritative when configured; otherwise X-Digi-Vault-Prefix may set it. digivault also enforces tenant→prefix server-side.",
            "title": "Vault Path Prefix"
          }
        },
        "required": [
          "prompt"
        ],
        "title": "WorkflowRequest",
        "type": "object"
      },
      "WorkflowResult": {
        "description": "Result of run_digigraph_workflow. Phase 0: backtest result only.",
        "properties": {
          "backtest_result": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "digiquant BacktestResult when workflow ran a backtest",
            "title": "Backtest Result"
          },
          "error_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Stable machine code for digichat (e.g. free_quota_exceeded); None on success",
            "title": "Error Code"
          },
          "message": {
            "default": "",
            "description": "Human-readable summary",
            "title": "Message",
            "type": "string"
          },
          "optimize_error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Error from optimize step without failing whole workflow",
            "title": "Optimize Error"
          },
          "optimize_result": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "digiquant OptimizeResult when optimize step ran",
            "title": "Optimize Result"
          },
          "profiling_questions": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Merged profiling questions (brief + trading profile gaps)",
            "title": "Profiling Questions"
          },
          "rag_sources": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Aggregated digisearch citations from the research step",
            "title": "Rag Sources"
          },
          "research_brief": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Structured research brief when research subgraph produced one",
            "title": "Research Brief"
          },
          "success": {
            "description": "Whether the workflow completed successfully",
            "title": "Success",
            "type": "boolean"
          }
        },
        "required": [
          "success"
        ],
        "title": "WorkflowResult",
        "type": "object"
      }
    }
  },
  "info": {
    "description": "Orchestration brain for digithings: LangGraph workflows, OpenAI-compatible chat, and federated vertical tools (digisearch, digiquant, digivault). Interactive docs: `/docs` (Swagger) and `/redoc`.",
    "title": "digigraph",
    "version": "0.1.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/files/{path}": {
      "get": {
        "description": "Serve exported files (CSV, JSON, Parquet) from run_data_dir.\nPath is relative to run_data_dir (e.g. default/export.csv). Only files under run_data_dir are allowed.",
        "operationId": "serve_file_files__path__get",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "required": true,
            "schema": {
              "title": "Path",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Serve File"
      }
    },
    "/health": {
      "get": {
        "description": "Legacy health check for Docker and digiclaw (kept for back-compat).",
        "operationId": "health_health_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "type": "string"
                  },
                  "title": "Response Health Health Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Health"
      }
    },
    "/healthz": {
      "get": {
        "description": "Minimal liveness probe. Auth-exempt, rate-limit-exempt, secret-free.\n\nContract: returns HTTP 200 with ``{\"ok\": true}``. Intended for load\nbalancers and k8s probes. For richer diagnostics, see digismith's\n``/v1/status``.",
        "operationId": "healthz_healthz_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "type": "boolean"
                  },
                  "title": "Response Healthz Healthz Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Healthz"
      }
    },
    "/test_llm": {
      "get": {
        "description": "Test digigraph → LiteLLM → Ollama (or configured provider).\nSame code path as workflow research node; no backtest.",
        "operationId": "test_llm_test_llm_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "boolean"
                      }
                    ]
                  },
                  "title": "Response Test Llm Test Llm Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Test Llm"
      }
    },
    "/threads/{thread_id}/history": {
      "get": {
        "description": "Return checkpoint history for a thread (debug). Most recent first.\nRequires a checkpointer. Each entry is a safe subset of state values.",
        "operationId": "get_thread_history_threads__thread_id__history_get",
        "parameters": [
          {
            "in": "path",
            "name": "thread_id",
            "required": true,
            "schema": {
              "title": "Thread Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Thread History"
      }
    },
    "/threads/{thread_id}/resume": {
      "post": {
        "description": "Resume a thread that was interrupted (e.g. after research when DIGI_INTERRUPT_AFTER_RESEARCH=1).\nOptional body: {\"resume\": <value>} passed to LangGraph Command(resume=...). Same graph config required.",
        "operationId": "resume_thread_threads__thread_id__resume_post",
        "parameters": [
          {
            "in": "path",
            "name": "thread_id",
            "required": true,
            "schema": {
              "title": "Thread Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/ResumeThreadRequest"
                  },
                  {
                    "type": "null"
                  }
                ],
                "title": "Body"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Resume Thread"
      }
    },
    "/threads/{thread_id}/state": {
      "get": {
        "description": "Return current (or specified) checkpoint state for a thread.\nRequires a checkpointer (default: memory when DIGI_CHECKPOINTER unset). Returns stored_datasets, research_response, error, etc.",
        "operationId": "get_thread_state_threads__thread_id__state_get",
        "parameters": [
          {
            "in": "path",
            "name": "thread_id",
            "required": true,
            "schema": {
              "title": "Thread Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "checkpoint_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Checkpoint Id"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Thread State"
      }
    },
    "/v1/chat/completions": {
      "post": {
        "description": "OpenAI-compatible chat completions. Runs RAG workflow (LLM + search) and returns\nthe response as a chat message. Use as a model in Open WebUI.\nWhen stream=true: progressive SSE with tool-call blocks then final answer.\nTo get Open WebUI–style tool blocks (<details>, markdown tables), send header\nX-Response-Format: openwebui or body openwebui_format=true. model=digigraph-rag alone\ndoes not enable that chrome. digichat sends X-Suppress-Tool-Stream /\nX-Response-Format: plain as belt-and-suspenders; activity arrives via digigraph_trace.",
        "operationId": "chat_completions_v1_chat_completions_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatCompletionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Chat Completions",
        "tags": [
          "openai-compatible"
        ]
      }
    },
    "/v1/debug/input_messages": {
      "get": {
        "description": "Return the last few chat completion request summaries (message count, content lengths, prompt preview).\nUse to inspect what the client is sending when debugging context or empty responses.",
        "operationId": "debug_input_messages_v1_debug_input_messages_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Debug Input Messages V1 Debug Input Messages Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Debug Input Messages",
        "tags": [
          "openai-compatible"
        ]
      }
    },
    "/v1/model-info": {
      "get": {
        "description": "Return the LLM model used for Project RAG completions. Use to validate config.",
        "operationId": "model_info_v1_model_info_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Model Info V1 Model Info Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Model Info",
        "tags": [
          "openai-compatible"
        ]
      }
    },
    "/v1/models": {
      "get": {
        "description": "List available models. Open WebUI discovers digigraph-rag here.",
        "operationId": "list_models_v1_models_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response List Models V1 Models Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Models",
        "tags": [
          "openai-compatible"
        ]
      }
    },
    "/v1/status": {
      "get": {
        "description": "Public project status. Secret-free: never exposes filesystem paths, URLs, or env-var values.\n\nFields surface the subset of the resolved `DigiProjectConfig` safe for unauthenticated\nconsumption (name, version, enabled agents, llm_mode, mcp.enabled, workflow_profile).\nFresh read on every request (mtime-cached inside `DigiProjectConfig.load()`).",
        "operationId": "status_v1_status_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Status V1 Status Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Status",
        "tags": [
          "openai-compatible"
        ]
      }
    },
    "/workflow": {
      "post": {
        "description": "digiclaw custom skill: run_digigraph_workflow.\nPhase 0: user idea → backtest via digiquant → result in < 10s.",
        "operationId": "run_digigraph_workflow",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkflowRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowResult"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Run digigraph workflow"
      }
    }
  }
}
