{"openapi":"3.1.0","info":{"title":"Oxagen API","version":"0.21.8"},"paths":{"/v1/ontology/nodes":{"post":{"tags":["ontology"],"summary":"Create Node Route","description":"Create a new ontology node in the caller's workspace.\n\nGoes through :func:`get_repository` so a workspace whose\n``WorkspaceGraphRouting`` is flipped to Neo4j writes into the\ngraph instance instead of Postgres. The post-write ``commit()``\nis still required because the Postgres adapter flushes but\nnever commits.","operationId":"create_node_route_v1_ontology_nodes_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeCreateRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["ontology"],"summary":"List Nodes Route","description":"List nodes in a workspace the caller can access (optionally filtered).","operationId":"list_nodes_route_v1_ontology_nodes_get","parameters":[{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":80,"pattern":"^[a-z_][a-z0-9_.:-]*$"},{"type":"null"}],"title":"Type"}},{"name":"connection_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Connection Id"}},{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Scope lists to this workspace when set; must be a workspace the caller belongs to. Omit to use the default workspace.","title":"Workspace Id"},"description":"Scope lists to this workspace when set; must be a workspace the caller belongs to. Omit to use the default workspace."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/NodeResponse"},"title":"Response List Nodes Route V1 Ontology Nodes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["ontology"],"summary":"Delete Nodes By Type Route","description":"Soft-delete all nodes of a given type and their incident edges.\n\nNodes and edges are marked ``is_deleted=true``; they are NOT\nhard-deleted. A future trash-purge endpoint will permanently remove\nsoft-deleted data.\n\nArgs:\n    type: Node type string (e.g. ``code.file``, ``person``).\n    user: Authenticated user from JWT.\n    session: DB session with RLS context.\n\nReturns:\n    Counts of soft-deleted nodes and edges.\n\nRaises:\n    HTTPException 400: If ``type`` param is missing or blank.","operationId":"delete_nodes_by_type_route_v1_ontology_nodes_delete","parameters":[{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"description":"Node type to delete. Required.","title":"Type"},"description":"Node type to delete. Required."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteNodesByTypeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ontology/nodes/typeahead":{"get":{"tags":["ontology"],"summary":"Nodes Typeahead Route","description":"Lightweight name-typeahead used by the memory-creation drawer.\n\nReturns up to ``limit`` nodes ranked by exact-match-then-importance\nwhen ``q`` is supplied, or a plain head-of-list when it isn't.\nOptionally constrained to a single ``type`` so the operator can\nnarrow the picker (e.g. only ``person`` nodes) before searching.\n\nNo credit gate -- read-only substring scan against the workspace\nbackend, the same one that powers ``graph_neighborhood``'s search.","operationId":"nodes_typeahead_route_v1_ontology_nodes_typeahead_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Free-text fragment to substring-match against ``Node.name`` (case-insensitive). When omitted, the first ``limit`` nodes of the optional ``type`` are returned so the picker can show a browsable starter list.","title":"Q"},"description":"Free-text fragment to substring-match against ``Node.name`` (case-insensitive). When omitted, the first ``limit`` nodes of the optional ``type`` are returned so the picker can show a browsable starter list."},{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":80,"pattern":"^[a-z_][a-z0-9_.:-]*$"},{"type":"null"}],"description":"Restrict results to a single node type. Applied on top of the name match when ``q`` is also set.","title":"Type"},"description":"Restrict results to a single node type. Applied on top of the name match when ``q`` is also set."},{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Workspace whose nodes to search. Must be a workspace the caller belongs to. Omit to use the caller's default.","title":"Workspace Id"},"description":"Workspace whose nodes to search. Must be a workspace the caller belongs to. Omit to use the caller's default."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/NodeResponse"},"title":"Response Nodes Typeahead Route V1 Ontology Nodes Typeahead Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ontology/graph_overview":{"get":{"tags":["ontology"],"summary":"Graph Overview Route","description":"Bounded supernode aggregation of a workspace graph.\n\nPowers the Explore tab default view at any scale. Returns at\nmost ``max_supernodes`` clusters regardless of underlying graph\nsize; the renderer can then expand a cluster on click via\n``GET /v1/ontology/nodes?type=<t>&workspace_id=<ws>`` (now capped\nat 10000 — the per-cluster payload that lets a single drill-down\nhold a whole cluster's members).\n\nPairs with the existing ``GET /v1/ontology/nodes`` and\n``GET /v1/ontology/edges`` so the navigation flow is:\n\n1. Initial page load: ``graph_overview`` → ~500 supernodes.\n2. Click supernode → ``GET /nodes?type=<t>`` returns its members.\n3. Click member → ``GET /edges?source_node_id=<id>`` for 1-hop\n   neighborhood.\n\nNo new credit gate — this is a read-only aggregation served\ndirectly by the workspace's ontology backend.","operationId":"graph_overview_route_v1_ontology_graph_overview_get","parameters":[{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Workspace to summarise. Must be a workspace the caller belongs to. Omit to use the caller's default workspace.","title":"Workspace Id"},"description":"Workspace to summarise. Must be a workspace the caller belongs to. Omit to use the caller's default workspace."},{"name":"max_supernodes","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":10,"description":"Hard cap on returned supernode clusters. Defaults to 500 — enough for code-graph workspaces with up to ~30 distinct top-level path segments per node type. Raise for finer-grained drill-down at the cost of payload size; lower for a coarser overview.","default":500,"title":"Max Supernodes"},"description":"Hard cap on returned supernode clusters. Defaults to 500 — enough for code-graph workspaces with up to ~30 distinct top-level path segments per node type. Raise for finer-grained drill-down at the cost of payload size; lower for a coarser overview."},{"name":"group_by","in":"query","required":false,"schema":{"enum":["type","type_path"],"type":"string","description":"Aggregation dimension. ``type_path`` groups by ``(node_type, first-segment-of-name)`` — the default — and yields useful clusters for code-graph workspaces (``services`` / ``packages`` / ``infra`` / ...). ``type`` collapses to one cluster per node type for a coarser overview when path bucketing is uninformative.","default":"type_path","title":"Group By"},"description":"Aggregation dimension. ``type_path`` groups by ``(node_type, first-segment-of-name)`` — the default — and yields useful clusters for code-graph workspaces (``services`` / ``packages`` / ``infra`` / ...). ``type`` collapses to one cluster per node type for a coarser overview when path bucketing is uninformative."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GraphOverviewRecord"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ontology/graph_stats":{"get":{"tags":["ontology"],"summary":"Graph Stats Route","description":"Workspace-level graph-health rollup for the StatsPanel.\n\nComputes all eight stat-box payloads (totals, by-type\ndistributions, per-connection counts, top hubs, degree\ndistribution, connectivity, density) over the entire workspace\nin a single round-trip from the client's perspective. The\nprovider issues two Cypher queries (one over nodes, one over\nedges) and the route layer enriches per-connection rows with\nhuman-readable labels from ``app.connections``.\n\nCounts include only live (non-deleted) nodes and edges. The\npayload bounds are predictable: at most ``top_hubs_limit`` hub\nrows (<= 50), one row per node ``type`` for the by-type\ndistribution, one row per relationship type for the edge\ndistribution, and at most ``N+1`` rows in ``by_connection``\n(where ``N`` is the count of distinct connections in the\nworkspace, plus the synthetic ``_manual`` row).\n\nNo new credit gate -- this is a read-only aggregation served\ndirectly by the workspace's ontology backend.","operationId":"graph_stats_route_v1_ontology_graph_stats_get","parameters":[{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Workspace whose graph stats to compute. Must be a workspace the caller belongs to. Omit to use the caller's default workspace.","title":"Workspace Id"},"description":"Workspace whose graph stats to compute. Must be a workspace the caller belongs to. Omit to use the caller's default workspace."},{"name":"top_hubs_limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"description":"Number of top-degree nodes to surface in the ``top_hubs`` rollup. Defaults to 5 to match the StatsPanel chart layout. Cap of 50 keeps the payload small even on dense workspaces.","default":5,"title":"Top Hubs Limit"},"description":"Number of top-degree nodes to surface in the ``top_hubs`` rollup. Defaults to 5 to match the StatsPanel chart layout. Cap of 50 keeps the payload small even on dense workspaces."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GraphStatsRecord"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ontology/graph_neighborhood":{"get":{"tags":["ontology"],"summary":"Graph Neighborhood Route","description":"Resolve a search / id to a 2-hop neighborhood subgraph.\n\nPowers the Explore tab's search box: the user types a name, the\nserver resolves it to the highest-importance match, expands the\nbidirectional N-hop neighborhood, and returns the subgraph plus\nthe candidate list so the UI can offer a picker if the match was\nambiguous.\n\nAll edge types are eligible — unlike :meth:`get_neighborhood`\n(which back the MCP tool and restricts to the code-graph\nallowlist), this variant surfaces every relationship in the\nworkspace so a user can see who/what is connected to whom across\ndomains.\n\nEither ``q`` or ``node_id`` is required.\n\nNo credit gate — read-only aggregation.","operationId":"graph_neighborhood_route_v1_ontology_graph_neighborhood_get","parameters":[{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Workspace whose graph to query. Must be a workspace the caller belongs to. Omit to use the caller's default.","title":"Workspace Id"},"description":"Workspace whose graph to query. Must be a workspace the caller belongs to. Omit to use the caller's default."},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Free-text search string matched (case-insensitive, substring) against ``Node.name``. The top-ranked match becomes the neighborhood center; a candidate list of up to 10 alternatives is returned for the UI to surface as a picker. Mutually exclusive with ``node_id``.","title":"Q"},"description":"Free-text search string matched (case-insensitive, substring) against ``Node.name``. The top-ranked match becomes the neighborhood center; a candidate list of up to 10 alternatives is returned for the UI to surface as a picker. Mutually exclusive with ``node_id``."},{"name":"node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Direct UUID of the node to center the neighborhood on. Skips the search step entirely. Mutually exclusive with ``q``.","title":"Node Id"},"description":"Direct UUID of the node to center the neighborhood on. Skips the search step entirely. Mutually exclusive with ``q``."},{"name":"hops","in":"query","required":false,"schema":{"type":"integer","maximum":3,"minimum":1,"description":"Number of bidirectional hops to expand from the center. Default 2 (Mac's ask). Capped at 3 to bound result size — beyond 3 a typical workspace blows past the node-limit budget anyway.","default":2,"title":"Hops"},"description":"Number of bidirectional hops to expand from the center. Default 2 (Mac's ask). Capped at 3 to bound result size — beyond 3 a typical workspace blows past the node-limit budget anyway."},{"name":"node_limit","in":"query","required":false,"schema":{"type":"integer","maximum":2000,"minimum":10,"description":"Cap on nodes returned. 300 keeps the Reagraph WebGL canvas snappy; raise for sparse-graph workspaces where 2 hops naturally fit more.","default":300,"title":"Node Limit"},"description":"Cap on nodes returned. 300 keeps the Reagraph WebGL canvas snappy; raise for sparse-graph workspaces where 2 hops naturally fit more."},{"name":"edge_limit","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"minimum":10,"description":"Cap on edges returned.","default":600,"title":"Edge Limit"},"description":"Cap on edges returned."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GraphNeighborhoodResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ontology/family_tree":{"get":{"tags":["ontology"],"summary":"Family Tree Route","description":"Expand the N-degree family tree from a center node.\n\nReturns every node reachable within ``degrees`` bidirectional hops\nfrom ``node_id``, plus every live edge whose endpoints are both\ninside that set. All edge types are eligible.\n\n\"Degrees of Separation\" follows the social-graph convention: a node\nat degree 1 is a direct neighbor; degree 2 is a neighbor's neighbor.\nThe integer node count is ``len(nodes)`` in the response.\n\nNo credit gate — read-only traversal.","operationId":"family_tree_route_v1_ontology_family_tree_get","parameters":[{"name":"node_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Center node UUID. The family tree expands outward from this node for ``degrees`` hops in all directions.","title":"Node Id"},"description":"Center node UUID. The family tree expands outward from this node for ``degrees`` hops in all directions."},{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Workspace whose graph to query. Must be a workspace the caller belongs to. Omit to use the caller's default.","title":"Workspace Id"},"description":"Workspace whose graph to query. Must be a workspace the caller belongs to. Omit to use the caller's default."},{"name":"degrees","in":"query","required":false,"schema":{"type":"integer","maximum":5,"minimum":1,"description":"Degrees of separation to expand. 1 = direct neighbors only; 2 = neighbors of neighbors; up to 5. Default 2.","default":2,"title":"Degrees"},"description":"Degrees of separation to expand. 1 = direct neighbors only; 2 = neighbors of neighbors; up to 5. Default 2."},{"name":"node_limit","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"minimum":10,"description":"Cap on total nodes returned (including center). Default 500.","default":500,"title":"Node Limit"},"description":"Cap on total nodes returned (including center). Default 500."},{"name":"edge_limit","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":10,"description":"Cap on edges returned. Default 1000.","default":1000,"title":"Edge Limit"},"description":"Cap on edges returned. Default 1000."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GraphNeighborhoodResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ontology/nodes/{node_id}":{"get":{"tags":["ontology"],"summary":"Get Node Route","description":"Fetch a single node by ID, scoped to the caller's chosen workspace.","operationId":"get_node_route_v1_ontology_nodes__node_id__get","parameters":[{"name":"node_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Node Id"}},{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Workspace the node should be looked up in; must be a workspace the caller belongs to. Omit to use the caller's default workspace. Required by the chat citation popover to resolve nodes in a non-default workspace.","title":"Workspace Id"},"description":"Workspace the node should be looked up in; must be a workspace the caller belongs to. Omit to use the caller's default workspace. Required by the chat citation popover to resolve nodes in a non-default workspace."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ontology/nodes/search":{"post":{"tags":["ontology"],"summary":"Search Nodes Route","description":"Semantic search over nodes using the routed backend.\n\nEmbeds the query with the workspace's configured embedding provider,\nthen delegates to :meth:`OntologyRepository.semantic_search`. The\nPostgres provider resolves to pgvector cosine; the Neo4j provider\nresolves to the ``node_embedding`` vector index.\n\nCredit gate: ``ontology.search.vector`` (cost 1). The gate fires\nbefore the embedding provider call so a zero-balance tenant is\nrejected with 402 before burning an embedding API call.","operationId":"search_nodes_route_v1_ontology_nodes_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeSearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/NodeResponse"},"type":"array","title":"Response Search Nodes Route V1 Ontology Nodes Search Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ontology/edges":{"post":{"tags":["ontology"],"summary":"Create Edge Route","description":"Create a new ontology edge between two nodes in the caller's workspace.\n\nGoes through the repository, so a cross-workspace edge attempt\nsurfaces as ``CrossWorkspaceEdgeError`` → HTTP 400 rather than\nsilently tying two workspaces together.","operationId":"create_edge_route_v1_ontology_edges_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EdgeCreateRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EdgeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["ontology"],"summary":"List Edges Route","description":"List edges in a workspace the caller can access.","operationId":"list_edges_route_v1_ontology_edges_get","parameters":[{"name":"source_node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Source Node Id"}},{"name":"target_node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Target Node Id"}},{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":80,"pattern":"^[A-Za-z_][A-Za-z0-9_.:-]*$"},{"type":"null"}],"title":"Type"}},{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Scope lists to this workspace when set; must be a workspace the caller belongs to. Omit to use the default workspace.","title":"Workspace Id"},"description":"Scope lists to this workspace when set; must be a workspace the caller belongs to. Omit to use the default workspace."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EdgeResponse"},"title":"Response List Edges Route V1 Ontology Edges Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ontology/edges/{edge_id}":{"get":{"tags":["ontology"],"summary":"Get Edge Route","description":"Fetch a single edge by ID.","operationId":"get_edge_route_v1_ontology_edges__edge_id__get","parameters":[{"name":"edge_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Edge Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EdgeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ontology/search":{"post":{"tags":["ontology"],"summary":"Hybrid ontology search (vector + structural)","description":"Hybrid search over workspace nodes (vector + structural).\n\nRanks nodes by ``vector_weight * vector_score +\nstructural_weight * structural_score``; when\n``config.search.importance_ranking`` is True, the combined score\nis multiplied by each node's ``importance_score``.\n\nThe credit gate (``ontology.search.hybrid``, cost 1) fires before\nany embedding call, so a zero-balance tenant is rejected with a\n402 before spending compute.\n\nArgs:\n    body: Validated search request.\n    receipt: Credit reservation receipt (auto-charged by the\n        ``require_credits`` dependency).\n    user: Authenticated caller.\n    session: Request-scoped session with RLS context set.\n\nReturns:\n    A ``HybridSearchResponse`` with the scored results, echoed\n    mode, query plan, and credit receipt.\n\nRaises:\n    HTTPException: 402 on insufficient credits; 404 when the\n        caller has no workspace.","operationId":"hybrid_search_route_v1_ontology_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HybridSearchRequest"}}},"required":true},"responses":{"200":{"description":"Ranked nodes with per-source score breakdown plus the credit receipt recorded on billing.credit_ledger for this call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HybridSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ontology/symbol-context":{"post":{"tags":["ontology"],"summary":"Aggregated graph context for a single code symbol","description":"One-call laser-context bundle for a code symbol.\n\nResolves the target via ``node_id`` (preferred) or ``(name, type)``\nand returns the full neighbourhood an agent needs to reason about\nthe impact of changing the symbol: the class it belongs to, sibling\nmethods, tests pairing on it, direct callers / callees, semantic\nreturns, and the most-recent ``touched`` commits with action labels\nand authors. Designed to replace the 5+ separate Cypher / MCP\ncalls an agent would otherwise stitch together.\n\nArgs:\n    body: Resolved request shape with caps on each result list.\n    receipt: 1-credit reservation auto-charged before any neo4j\n        call so a zero-balance tenant 402s before spending compute.\n    user: Authenticated caller.\n    session: Workspace-scoped session.\n\nReturns:\n    :class:`SymbolContextResponse` with every collection populated\n    (or empty) under the requested caps.\n\nRaises:\n    HTTPException: 400 when neither ``node_id`` nor ``(name, type)``\n        is supplied; 404 when the target cannot be resolved; 409\n        when the ``(name, type)`` pair is ambiguous.","operationId":"symbol_context_route_v1_ontology_symbol_context_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SymbolContextRequest"}}},"required":true},"responses":{"200":{"description":"Containing class, sibling methods, tests, callers, callees, semantic returns, and recent commits with action label + author — collapsed into one round trip so an agent does not have to fan out 5+ MCP calls to gather impact-analysis context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SymbolContextResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ontology/prompt":{"post":{"tags":["ontology"],"summary":"Unified update / query / both ontology prompt","description":"Unified update/query endpoint - the day-1 demo entry point.\n\n1. Resolve the caller's workspace + tenant.\n2. Classify intent (unless ``force_intent`` is set).\n3. Reserve credits via ``check_and_reserve_credits``. 402 on empty\n   balance.\n4. Wrap the refiner + answerer pipeline in ``try/except``.\n   - On success: persist nodes + edges, run the answerer, commit,\n     write ``OntologyPromptRun(status='ok')``, emit analytics.\n   - On error: rollback, refund credits, write\n     ``OntologyPromptRun(status='error')``, emit analytics, then\n     re-raise.\n5. Echo ``X-Correlation-Id`` back to the caller.\n\nArgs:\n    body: Request payload.\n    response: FastAPI response, used to set the correlation header.\n    user: Authenticated caller.\n    session: Request-scoped DB session.\n\nReturns:\n    The populated PromptResponse.\n\nRaises:\n    HTTPException: 402 on insufficient credits, 404 on missing\n        workspace/tenant. Pipeline exceptions are re-raised\n        after the audit + refund is recorded.","operationId":"prompt_route_v1_ontology_prompt_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptRequest"}}},"required":true},"responses":{"200":{"description":"Pipeline outcome: persisted nodes + edges, optional question-answerer result, and the correlation id echoed in X-Correlation-Id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/ontology/prompt/stream":{"post":{"tags":["ontology"],"summary":"Stream chain-of-thought question answering via SSE","description":"Stream question-answering pipeline steps as Server-Sent Events.\n\nRuns only the ``query`` pipeline. The update / both intents are\nhandled by ``POST /v1/ontology/prompt`` (sync).\n\nThe pre-flight checks (workspace resolution, credit reservation)\nrun on the request-scoped ``session`` here in the route handler.\nThe actual pipeline runs inside ``_stream_prompt`` which opens its\nown session, because FastAPI closes the dependency-injected session\nas soon as this handler returns — before the async generator runs.\n\nSteps emitted in order:\n1. ``embedding`` start / done\n2. ``retrieval`` start / done\n3. ``llm_call`` start / done\n4. ``parse`` start / done\n5. Terminal ``done`` (narrative + citations) or ``error``\n\nCredit cost matches ``ontology.prompt.query`` — same as the sync\nendpoint for a ``query`` intent.\n\nArgs:\n    body: Stream request payload.\n    user: Authenticated caller.\n    session: Request-scoped DB session (used for pre-flight only).\n\nReturns:\n    A ``StreamingResponse`` with ``Content-Type: text/event-stream``.\n\nRaises:\n    HTTPException: 402 on insufficient credits, 404 on missing\n        workspace.","operationId":"prompt_stream_route_v1_ontology_prompt_stream_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptStreamRequest"}}},"required":true},"responses":{"200":{"description":"SSE stream of pipeline steps and final answer.","content":{"application/json":{"schema":{}},"text/event-stream":{}}},"402":{"description":"Insufficient credits."},"404":{"description":"No workspace found."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/mcp/token":{"post":{"tags":["mcp"],"summary":"Mint Mcp Token Route","description":"Mint an MCP-audience JWT for the caller's selected workspace.\n\nThe caller must already be authenticated (session cookie / bearer\nJWT) and be a member of the requested workspace. The returned\ntoken is what the MCP host (Claude Desktop, marketplace listing,\netc.) presents as ``Authorization: Bearer ...`` to the MCP SSE\nendpoint — see ``services/mcp-server/auth.py`` for verification.\n\nRate-limited via ``rate_authenticated`` (60 req / minute / user)\nso a compromised session can't be amplified into many independent\nlong-lived MCP tokens before revocation kicks in.\n\nArgs:\n    request: Raw request (slowapi key extractor).\n    body: Request body specifying ``workspace_id`` and optional\n        ``expires_in_days``.\n    user: Authenticated caller (injected by dependency).\n    session: Request-scoped RLS session.\n\nReturns:\n    The minted JWT plus echoed TTL metadata.\n\nRaises:\n    HTTPException 404: Workspace missing or caller not a member.","operationId":"mint_mcp_token_route_v1_mcp_token_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintMCPTokenRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintMCPTokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/mcp-tokens":{"post":{"tags":["mcp"],"summary":"Create Mcp Token","description":"Mint a new MCP-audience bearer token for this workspace.\n\nThe plaintext token is returned once — copy it immediately. The\ntoken authenticates against the MCP server's SSE endpoint with\n``Authorization: Bearer <token>``.\n\nArgs:\n    workspace_id: Workspace to scope the token to.\n    body: Token name and optional TTL.\n    user: Authenticated caller (must be a workspace member).\n    session: RLS-bound session.\n\nReturns:\n    The minted token row plus the one-time plaintext.\n\nRaises:\n    HTTPException 404: Workspace not found or caller is not a\n        member.","operationId":"create_mcp_token_v1_workspaces__workspace_id__mcp_tokens_post","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpTokenCreateBody"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpTokenCreateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["mcp"],"summary":"List Mcp Tokens","description":"List the **caller's** MCP tokens for this workspace.\n\nVisibility is owner-only: workspace admins do **not** see tokens\nminted by other members. MCP tokens are user-bound credentials\n(the bearer can act as that user); exposing other members'\nprefixes / metadata to admins would weaken the credential model\nwithout serving an operational need (admins revoke users, not\nindividual tokens). If workspace-level visibility is ever needed,\nadd a separate admin-gated endpoint rather than relaxing this one.\n\nReturns active and revoked tokens (revoked rows are kept as an\naudit trail). Expired tokens are included.\n\nArgs:\n    workspace_id: Workspace to scope the query to.\n    user: Authenticated caller (must be a workspace member).\n    session: RLS-bound session.\n\nReturns:\n    Caller-owned MCP token projections for this workspace,\n    newest first.\n\nRaises:\n    HTTPException 404: Workspace not found or caller not a member.","operationId":"list_mcp_tokens_v1_workspaces__workspace_id__mcp_tokens_get","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeyRow"},"title":"Response List Mcp Tokens V1 Workspaces  Workspace Id  Mcp Tokens Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/mcp-tokens/{key_id}":{"delete":{"tags":["mcp"],"summary":"Revoke Mcp Token","description":"Revoke an MCP token — sets ``revoked_at`` but keeps audit row.\n\nOnly the token's owner can revoke it. Revoking a token that is\nalready revoked is a no-op (idempotent).\n\nArgs:\n    workspace_id: Workspace the token belongs to.\n    key_id: Token UUID to revoke.\n    user: Authenticated caller (must own the token).\n    session: RLS-bound session.\n\nRaises:\n    HTTPException 404: Token not found, not owned by caller, or\n        not an MCP-audience token for this workspace.","operationId":"revoke_mcp_token_v1_workspaces__workspace_id__mcp_tokens__key_id__delete","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"key_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Key Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/runs":{"post":{"tags":["runs"],"summary":"Dispatch an agent execution","description":"Create an Execution and enqueue the first Task(s). If ``idempotency_key`` matches a prior dispatch, the prior execution is returned with ``was_duplicate=true``.","operationId":"post_run_v1_runs_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DispatchRunRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DispatchRunResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/approvals/{approval_id}/resolve":{"post":{"tags":["runs"],"summary":"Resolve a pending human-approval request","description":"Approve or reject an agent action that requires human sign-off. On APPROVED, re-enqueues the suspended Run. On REJECTED, transitions the Run to FAILED.","operationId":"post_resolve_approval_v1_approvals__approval_id__resolve_post","parameters":[{"name":"approval_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Approval Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveApprovalRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveApprovalResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/me/api-keys/scopes":{"get":{"tags":["auth"],"summary":"List Known Scopes","description":"Return the canonical scope catalogue.\n\nUse the returned strings in the ``scopes`` field of\n``POST /v1/auth/me/api-keys``. Unknown values are silently\ndropped at create time; this endpoint lets clients discover the\nvalid set without hitting that surprise.\n\nReturns:\n    Sorted list of scope strings.","operationId":"list_known_scopes_v1_auth_me_api_keys_scopes_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"type":"string"},"type":"array","title":"Response List Known Scopes V1 Auth Me Api Keys Scopes Get"}}}}}}},"/v1/auth/me/api-keys":{"get":{"tags":["auth"],"summary":"List Api Keys","description":"List the caller's API keys, newest first.\n\nRevoked keys are included so the user sees the full audit trail.\n\nArgs:\n    user: Authenticated user.\n    session: RLS-bound session.\n\nReturns:\n    List of key projections.","operationId":"list_api_keys_v1_auth_me_api_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ApiKeyRow"},"type":"array","title":"Response List Api Keys V1 Auth Me Api Keys Get"}}}}}},"post":{"tags":["auth"],"summary":"Create Api Key","description":"Mint a new API key scoped to a workspace.\n\nThe plaintext token is returned **once** in the response — the\nclient must copy and store it. Subsequent reads only return the\nprefix.\n\nWorks with either JWT or API-key authentication so CI / SRE\nautomation can mint and rotate keys without going through the\nweb app.\n\nArgs:\n    body: Create request payload.\n    user: Authenticated user (JWT or API-key auth).\n    session: RLS-bound session.\n\nReturns:\n    The created key row plus the plaintext bearer token.\n\nRaises:\n    HTTPException: 404 when the workspace is not visible to the\n        caller.","operationId":"create_api_key_v1_auth_me_api_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreateRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/me/api-keys/{api_key_id}":{"get":{"tags":["auth"],"summary":"Get Api Key","description":"Fetch a single key by id.\n\nArgs:\n    api_key_id: Row to fetch.\n    user: Authenticated user.\n    session: RLS-bound session.\n\nReturns:\n    The key projection.\n\nRaises:\n    HTTPException: 404 when the key doesn't belong to the caller.","operationId":"get_api_key_v1_auth_me_api_keys__api_key_id__get","parameters":[{"name":"api_key_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Api Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRow"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["auth"],"summary":"Revoke Api Key","description":"Revoke a key — marks ``revoked_at`` but keeps the audit row.\n\nWorks with either JWT or API-key authentication. A caller that\nauthenticates with the key it is revoking will find the key\ninactive on the *next* request — the current request completes\nnormally because auth was resolved before the revoke ran.\n\nArgs:\n    api_key_id: Row to revoke.\n    user: Authenticated user.\n    session: RLS-bound session.\n\nReturns:\n    The updated key row.\n\nRaises:\n    HTTPException: 404 when the key doesn't belong to the caller.","operationId":"revoke_api_key_v1_auth_me_api_keys__api_key_id__delete","parameters":[{"name":"api_key_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Api Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRow"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/me/api-keys/{api_key_id}/usage":{"get":{"tags":["auth"],"summary":"Get Api Key Usage","description":"Return per-day usage counts for the last ``days`` days.\n\nArgs:\n    api_key_id: Row to summarise.\n    days: Window size in days (default 30, max 90).\n    user: Authenticated user.\n    session: RLS-bound session.\n\nReturns:\n    Aggregate counts plus a daily series.\n\nRaises:\n    HTTPException: 404 when the key doesn't belong to the caller.","operationId":"get_api_key_usage_v1_auth_me_api_keys__api_key_id__usage_get","parameters":[{"name":"api_key_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Api Key Id"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyUsageSummary"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/agent.claim_work":{"post":{"tags":["capabilities","capabilities:write"],"summary":"Claim a target node for an active session. At most one active claim per target is allowed — the multi-level conflict walker traverses the 'contains' hierarchy up and down. Same-session re-claim updates intent instead of creating a duplicate. Returns claim_id or raises on conflict. [write]","description":"Claim a target node for an active session. At most one active claim per target is allowed — the multi-level conflict walker traverses the 'contains' hierarchy up and down. Same-session re-claim updates intent instead of creating a duplicate. Returns claim_id or raises on conflict.","operationId":"capability_agent_claim_work_v1_cap_agent_claim_work_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentClaimWorkInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentClaimWorkOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/agent.end_session":{"post":{"tags":["capabilities","capabilities:write"],"summary":"End an agent session and cascade any still-active claims to 'abandoned'. Idempotent. Pass outcome='failed' with an error_signature to participate in the SPEC §6.2 failure cluster pipeline. [write]","description":"End an agent session and cascade any still-active claims to 'abandoned'. Idempotent. Pass outcome='failed' with an error_signature to participate in the SPEC §6.2 failure cluster pipeline.","operationId":"capability_agent_end_session_v1_cap_agent_end_session_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentEndSessionInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentEndSessionOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/agent.get_findings":{"post":{"tags":["capabilities","capabilities:read"],"summary":"List agent.finding nodes in the workspace, optionally filtered by target_node_id and/or severity. Scope by target_node_id for exhaustive results; unscoped queries are capped at 200 rows. [read]","description":"List agent.finding nodes in the workspace, optionally filtered by target_node_id and/or severity. Scope by target_node_id for exhaustive results; unscoped queries are capped at 200 rows.","operationId":"capability_agent_get_findings_v1_cap_agent_get_findings_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentGetFindingsInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentGetFindingsOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/agent.heartbeat":{"post":{"tags":["capabilities","capabilities:write"],"summary":"Stamp a heartbeat on an active agent session to prevent the worker sweeper from abandoning it. Returns the session's current status — stop heartbeating when already_inactive=true. [write]","description":"Stamp a heartbeat on an active agent session to prevent the worker sweeper from abandoning it. Returns the session's current status — stop heartbeating when already_inactive=true.","operationId":"capability_agent_heartbeat_v1_cap_agent_heartbeat_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentHeartbeatInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentHeartbeatOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/agent.list_active_claims":{"post":{"tags":["capabilities","capabilities:read"],"summary":"List active agent.claim nodes. Filter by session_id or target_node_id for exhaustive SQL-pushed results; unscoped queries are capped at 200 active rows. [read]","description":"List active agent.claim nodes. Filter by session_id or target_node_id for exhaustive SQL-pushed results; unscoped queries are capped at 200 active rows.","operationId":"capability_agent_list_active_claims_v1_cap_agent_list_active_claims_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentListActiveClaimsInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentListActiveClaimsOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/agent.read_decisions":{"post":{"tags":["capabilities","capabilities:read"],"summary":"Read decision steps for a given run. Set head_only=True to drop superseded rows and return only chain heads. [read]","description":"Read decision steps for a given run. Set head_only=True to drop superseded rows and return only chain heads.","operationId":"capability_agent_read_decisions_v1_cap_agent_read_decisions_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentReadDecisionsInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentReadDecisionsOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/agent.record_decision":{"post":{"tags":["capabilities","capabilities:write"],"summary":"Record an auditable decision ('chose Y because Z, considered A, B, C') as a DECISION step on the active run. Optional supersedes_step_id records revision lineage. The step is appended to run.step and rides the audit hash chain + outbox. [write]","description":"Record an auditable decision ('chose Y because Z, considered A, B, C') as a DECISION step on the active run. Optional supersedes_step_id records revision lineage. The step is appended to run.step and rides the audit hash chain + outbox.","operationId":"capability_agent_record_decision_v1_cap_agent_record_decision_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRecordDecisionInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRecordDecisionOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/agent.record_finding":{"post":{"tags":["capabilities","capabilities:write"],"summary":"Attach a structured finding (bug, dead_code, complexity, ...) to an existing code.* node. Targets must be code.* type. Returns finding_id for downstream retrieval via agent.get_findings. [write]","description":"Attach a structured finding (bug, dead_code, complexity, ...) to an existing code.* node. Targets must be code.* type. Returns finding_id for downstream retrieval via agent.get_findings.","operationId":"capability_agent_record_finding_v1_cap_agent_record_finding_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRecordFindingInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRecordFindingOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/agent.release_claim":{"post":{"tags":["capabilities","capabilities:write"],"summary":"Release an active claim so other sessions may work on the same target. Owner-only — the JWT caller must be the user that opened the claim. Idempotent on already released or abandoned claims. [write]","description":"Release an active claim so other sessions may work on the same target. Owner-only — the JWT caller must be the user that opened the claim. Idempotent on already released or abandoned claims.","operationId":"capability_agent_release_claim_v1_cap_agent_release_claim_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentReleaseClaimInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentReleaseClaimOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/agent.start_session":{"post":{"tags":["capabilities","capabilities:write"],"summary":"Open a new agent task session. Returns the session_id that subsequent agent.heartbeat, agent.claim_work, and agent.end_session calls must reference. [write]","description":"Open a new agent task session. Returns the session_id that subsequent agent.heartbeat, agent.claim_work, and agent.end_session calls must reference.","operationId":"capability_agent_start_session_v1_cap_agent_start_session_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentStartSessionInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentStartSessionOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/billing.credits_balance":{"post":{"tags":["capabilities","capabilities:read"],"summary":"Read the current credit balance for the caller's tenant. [read]","description":"Read the current credit balance for the caller's tenant.","operationId":"capability_billing_credits_balance_v1_cap_billing_credits_balance_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingCreditsBalanceInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingCreditsBalanceOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/ontology.ask":{"post":{"tags":["capabilities","capabilities:read"],"summary":"Ask a natural-language question over your workspace ontology. Runs hybrid semantic + structural retrieval then composes a grounded answer with node citations. Returns narrative, cited nodes, candidate count, and retrieval mode. [read]","description":"Ask a natural-language question over your workspace ontology. Runs hybrid semantic + structural retrieval then composes a grounded answer with node citations. Returns narrative, cited nodes, candidate count, and retrieval mode.","operationId":"capability_ontology_ask_v1_cap_ontology_ask_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyAskInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyAskOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/ontology.explain_function":{"post":{"tags":["capabilities","capabilities:read"],"summary":"Return the full edge neighbourhood for a named function: what it calls, throws, reads, writes, returns, and the tests that cover it. Useful for understanding a function's impact before refactoring. [read]","description":"Return the full edge neighbourhood for a named function: what it calls, throws, reads, writes, returns, and the tests that cover it. Useful for understanding a function's impact before refactoring.","operationId":"capability_ontology_explain_function_v1_cap_ontology_explain_function_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyExplainFunctionInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyExplainFunctionOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/ontology.family_tree":{"post":{"tags":["capabilities","capabilities:read"],"summary":"Expand the N-degree family tree from a center node. Returns every live node reachable within degrees_of_separation bidirectional hops plus every live edge between those nodes. All edge types eligible. Degree 1 = direct neighbors; degree 2 = neighbors of neighbors. Capped at 5 degrees. [read]","description":"Expand the N-degree family tree from a center node. Returns every live node reachable within degrees_of_separation bidirectional hops plus every live edge between those nodes. All edge types eligible. Degree 1 = direct neighbors; degree 2 = neighbors of neighbors. Capped at 5 degrees.","operationId":"capability_ontology_family_tree_v1_cap_ontology_family_tree_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyFamilyTreeInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyFamilyTreeOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/ontology.delete_edge":{"post":{"tags":["capabilities","capabilities:write"],"summary":"Soft-delete a directed edge from the caller's workspace. The relationship remains in the audit log but is excluded from all live graph reads and traversals. [write]","description":"Soft-delete a directed edge from the caller's workspace. The relationship remains in the audit log but is excluded from all live graph reads and traversals.","operationId":"capability_ontology_delete_edge_v1_cap_ontology_delete_edge_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyDeleteEdgeInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyDeleteEdgeOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/ontology.delete_node":{"post":{"tags":["capabilities","capabilities:write"],"summary":"Soft-delete a node (and optionally its incident edges) from the caller's workspace. The node remains queryable for audit but is excluded from all live graph reads. [write]","description":"Soft-delete a node (and optionally its incident edges) from the caller's workspace. The node remains queryable for audit but is excluded from all live graph reads.","operationId":"capability_ontology_delete_node_v1_cap_ontology_delete_node_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyDeleteNodeInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyDeleteNodeOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/ontology.delete_nodes_by_type":{"post":{"tags":["capabilities","capabilities:write"],"summary":"Soft-delete every live node of a given type in the caller's workspace. Incident edges are cascaded in the same query. The type catalog row itself is preserved — use ontology.delete_type to drop the type as well. Destructive: requires confirmation='CONFIRMED'. [write]","description":"Soft-delete every live node of a given type in the caller's workspace. Incident edges are cascaded in the same query. The type catalog row itself is preserved — use ontology.delete_type to drop the type as well. Destructive: requires confirmation='CONFIRMED'.","operationId":"capability_ontology_delete_nodes_by_type_v1_cap_ontology_delete_nodes_by_type_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyDeleteNodesByTypeInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyDeleteNodesByTypeOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/ontology.delete_type":{"post":{"tags":["capabilities","capabilities:write"],"summary":"Soft-delete a type from the workspace catalog and cascade the deletion to every live node (or edge) of that type. The type row and all entities remain in the audit log but are excluded from live graph reads. [write]","description":"Soft-delete a type from the workspace catalog and cascade the deletion to every live node (or edge) of that type. The type row and all entities remain in the audit log but are excluded from live graph reads.","operationId":"capability_ontology_delete_type_v1_cap_ontology_delete_type_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyDeleteTypeInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyDeleteTypeOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/memory.forget":{"post":{"tags":["capabilities","capabilities:write"],"summary":"Soft-delete an Episode or Procedure memory node. Pinned or tenant-policy memories require require_grant=true. Returns forgotten=false when the node is missing. [write]","description":"Soft-delete an Episode or Procedure memory node. Pinned or tenant-policy memories require require_grant=true. Returns forgotten=false when the node is missing.","operationId":"capability_memory_forget_v1_cap_memory_forget_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryForgetInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryForgetOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/memory.procedure_for":{"post":{"tags":["capabilities","capabilities:read"],"summary":"Exact lookup of a Procedure by trigger pattern. Returns the matched Procedure or a null-id envelope on miss. Use memory.recall when the exact trigger is not known. [read]","description":"Exact lookup of a Procedure by trigger pattern. Returns the matched Procedure or a null-id envelope on miss. Use memory.recall when the exact trigger is not known.","operationId":"capability_memory_procedure_for_v1_cap_memory_procedure_for_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryProcedureForInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryProcedureForOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/memory.recall":{"post":{"tags":["capabilities","capabilities:read"],"summary":"Return procedures-first SPEC §6.4 memory envelope ranked by salience for the given intent. Optionally scope to a specific code symbol or outcome. [read]","description":"Return procedures-first SPEC §6.4 memory envelope ranked by salience for the given intent. Optionally scope to a specific code symbol or outcome.","operationId":"capability_memory_recall_v1_cap_memory_recall_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryRecallInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryRecallOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/memory.remember":{"post":{"tags":["capabilities","capabilities:write"],"summary":"Persist a fact as a graph Episode anchored to the active agent session. The Episode is immediately retrievable via memory.recall. [write]","description":"Persist a fact as a graph Episode anchored to the active agent session. The Episode is immediately retrievable via memory.recall.","operationId":"capability_memory_remember_v1_cap_memory_remember_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryRememberInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryRememberOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/ontology.get_edge":{"post":{"tags":["capabilities","capabilities:read"],"summary":"Fetch a single edge by id from the caller's workspace. [read]","description":"Fetch a single edge by id from the caller's workspace.","operationId":"capability_ontology_get_edge_v1_cap_ontology_get_edge_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyGetEdgeInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyGetEdgeOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/ontology.impact_of":{"post":{"tags":["capabilities","capabilities:read"],"summary":"Reverse traversal: given a symbol name, return all functions that read, write, modify, or calculate it. Useful for impact analysis before changing a shared variable or type. [read]","description":"Reverse traversal: given a symbol name, return all functions that read, write, modify, or calculate it. Useful for impact analysis before changing a shared variable or type.","operationId":"capability_ontology_impact_of_v1_cap_ontology_impact_of_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyImpactOfInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyImpactOfOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/ontology.rename_type":{"post":{"tags":["capabilities","capabilities:write"],"summary":"Rename a type and re-stamp every live node (or edge) of that type in the caller's workspace. The ontology.types catalog row is also updated atomically. [write]","description":"Rename a type and re-stamp every live node (or edge) of that type in the caller's workspace. The ontology.types catalog row is also updated atomically.","operationId":"capability_ontology_rename_type_v1_cap_ontology_rename_type_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyRenameTypeInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologyRenameTypeOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/ontology.search":{"post":{"tags":["capabilities","capabilities:read"],"summary":"Hybrid ontology search over the caller's workspace (vector + structural). [read]","description":"Hybrid ontology search over the caller's workspace (vector + structural).","operationId":"capability_ontology_search_v1_cap_ontology_search_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologySearchInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologySearchOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cap/ontology.symbol_context":{"post":{"tags":["capabilities","capabilities:read"],"summary":"One-call laser-context bundle for a symbol: the containing class, sibling methods, tests, callers, callees, semantic returns, and the most-recent commits that touched it. Pass either 'name' or 'node_id'. Replaces 5+ separate ontology.* traversal calls. [read]","description":"One-call laser-context bundle for a symbol: the containing class, sibling methods, tests, callers, callees, semantic returns, and the most-recent commits that touched it. Pass either 'name' or 'node_id'. Replaces 5+ separate ontology.* traversal calls.","operationId":"capability_ontology_symbol_context_v1_cap_ontology_symbol_context_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect.","title":"Idempotency-Key"},"description":"Optional caller-supplied key. Retrying a non-read capability with the same key within 24h returns the cached result instead of re-executing the side effect."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologySymbolContextInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OntologySymbolContextOutput"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhooks":{"get":{"tags":["webhooks"],"summary":"List webhook subscriptions","description":"List all (non-deleted) webhook subscriptions for the workspace.","operationId":"list_endpoints_route_v1_webhooks_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/WebhookEndpointPublic"},"type":"array","title":"Response List Endpoints Route V1 Webhooks Get"}}}}}},"post":{"tags":["webhooks"],"summary":"Register a webhook subscription","description":"Create a webhook subscription on the caller's workspace.\n\nReturns the endpoint record and the **raw signing secret** —\nstore it client-side immediately. The secret is never returned\nagain; rotation re-mints both halves.","operationId":"create_endpoint_route_v1_webhooks_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreated"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhooks/{endpoint_id}":{"get":{"tags":["webhooks"],"summary":"Read a webhook subscription","description":"Return one webhook subscription by id.","operationId":"get_endpoint_route_v1_webhooks__endpoint_id__get","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Endpoint Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["webhooks"],"summary":"Update a webhook subscription","description":"Patch one webhook subscription's mutable fields.","operationId":"update_endpoint_route_v1_webhooks__endpoint_id__patch","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Endpoint Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["webhooks"],"summary":"Soft-delete a webhook subscription","description":"Soft-delete an endpoint; past delivery rows remain queryable.","operationId":"delete_endpoint_route_v1_webhooks__endpoint_id__delete","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Endpoint Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhooks/{endpoint_id}/rotate-secret":{"post":{"tags":["webhooks"],"summary":"Rotate the signing secret","description":"Mint a new signing secret. The old secret is invalidated.","operationId":"rotate_secret_route_v1_webhooks__endpoint_id__rotate_secret_post","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Endpoint Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreated"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhooks/{endpoint_id}/test":{"post":{"tags":["webhooks"],"summary":"Send a synthetic ping event","description":"Enqueue a synthetic ``webhook.test`` delivery to the endpoint.\n\nSkips the dispatcher's filter eval — test pings always fire even\nif the endpoint's filter would otherwise reject them.","operationId":"test_ping_route_v1_webhooks__endpoint_id__test_post","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Endpoint Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestPingResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/webhooks/{endpoint_id}/deliveries":{"get":{"tags":["webhooks"],"summary":"Inspect recent delivery attempts","description":"Return up to ``limit`` recent delivery rows, newest-first.","operationId":"list_deliveries_route_v1_webhooks__endpoint_id__deliveries_get","parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Endpoint Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDeliveryPublic"},"title":"Response List Deliveries Route V1 Webhooks  Endpoint Id  Deliveries Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/events/kinds":{"get":{"tags":["events"],"summary":"List base ontology event kinds available for filtering","description":"Static catalog of base event kinds for the definition modal.\n\nReturns the same list for every workspace — the catalog is owned\nby the ontology event taxonomy, not by per-workspace data. The\nendpoint is workspace-gated only so the typeahead doesn't leak\nthe catalog to unauthenticated callers.","operationId":"list_kinds_route_v1_events_kinds_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/BaseEventKind"},"type":"array","title":"Response List Kinds Route V1 Events Kinds Get"}}}}}}},"/v1/events/types":{"get":{"tags":["events"],"summary":"List node + edge types observed in the workspace graph","description":"Return the union of node and edge types in the workspace.\n\nPowers the ``types`` typeahead in the event-definition modal so\nthe user picks from real workspace types instead of guessing.\nSourced from ``graph_stats`` (Neo4j over the live graph), pre-\nsorted by count desc.","operationId":"list_types_route_v1_events_types_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/WorkspaceTypeRow"},"type":"array","title":"Response List Types Route V1 Events Types Get"}}}}}}},"/v1/events/slugs":{"get":{"tags":["events"],"summary":"List custom event slug definitions","description":"Return every custom event slug defined in the workspace.","operationId":"list_slugs_route_v1_events_slugs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SlugDefPublic"},"type":"array","title":"Response List Slugs Route V1 Events Slugs Get"}}}}}},"post":{"tags":["events"],"summary":"Define a custom event slug","description":"Create a new custom event slug.\n\nThe ``filter_json`` field accepts the same DSL used by webhook\nendpoints; see ``oxagen.webhooks.filter_dsl`` for the schema.","operationId":"create_slug_route_v1_events_slugs_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSlugRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlugDefPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/events/slugs/{slug_id}":{"patch":{"tags":["events"],"summary":"Update a custom event slug","description":"Patch one slug definition's mutable fields.","operationId":"update_slug_route_v1_events_slugs__slug_id__patch","parameters":[{"name":"slug_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Slug Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSlugRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlugDefPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["events"],"summary":"Soft-delete a custom event slug","description":"Soft-delete a slug definition.\n\nExisting webhook endpoints filtering on this slug stop matching\nimmediately; their delivery history is preserved.","operationId":"delete_slug_route_v1_events_slugs__slug_id__delete","parameters":[{"name":"slug_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Slug Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/events/stream":{"get":{"tags":["events"],"summary":"Live SSE feed of workspace events","description":"Stream live workspace events as SSE.\n\n``slug`` and ``kind`` are independent filters — both apply (AND)\nwhen both are present. The endpoint long-polls the bus with a\n1s tick and a 15s heartbeat; the caller reconnects every ~30\nminutes to keep load balancer timeouts happy.","operationId":"stream_events_route_v1_events_stream_get","parameters":[{"name":"slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter to one custom slug (matches ``OntologyEventDef.name``).","title":"Slug"},"description":"Filter to one custom slug (matches ``OntologyEventDef.name``)."},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter to one event kind (e.g. ``node.created``).","title":"Kind"},"description":"Filter to one event kind (e.g. ``node.created``)."}],"responses":{"200":{"description":"SSE stream — one ``event: event\\ndata: {json}\\n\\n`` frame per event. Heartbeat comments fire every 15s.","content":{"application/json":{"schema":{}},"text/event-stream":{}}},"404":{"description":"No workspace available for caller."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/events/recent":{"get":{"tags":["events"],"summary":"Recent workspace events (oldest-first)","description":"Hydrate the SSE stream with the last ``limit`` events.","operationId":"recent_events_route_v1_events_recent_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RecentEventRow"},"title":"Response Recent Events Route V1 Events Recent Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/events/slugs/dry-run":{"post":{"tags":["events"],"summary":"Test a candidate event filter against recent events","description":"Replay a candidate filter against recent workspace events.","operationId":"dry_run_slug_route_v1_events_slugs_dry_run_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DryRunRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DryRunResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/events/subscribers":{"get":{"tags":["events"],"summary":"Webhooks + agent triggers subscribed to a slug","description":"Return every webhook + agent-trigger that fires on this slug.","operationId":"list_subscribers_route_v1_events_subscribers_get","parameters":[{"name":"event_def_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Event definition whose subscribers to enumerate.","title":"Event Def Id"},"description":"Event definition whose subscribers to enumerate."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribersResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/events/analytics":{"get":{"tags":["events"],"summary":"Volume + breakdown rollups for workspace events","description":"Return ClickHouse-backed event rollups for the workspace.\n\nReads from ``oxagen_events.ontology_events``. ``slug`` filters\nby the ``metadata.event_slug`` projection populated by the\nwebhook dispatcher when a slug resolved.","operationId":"analytics_route_v1_events_analytics_get","parameters":[{"name":"range","in":"query","required":false,"schema":{"type":"string","description":"1h | 24h | 7d | 30d","default":"24h","title":"Range"},"description":"1h | 24h | 7d | 30d"},{"name":"slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"}},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memories":{"post":{"tags":["memories"],"summary":"Create Memory Route","description":"Create a memory and link it to the named workspace nodes.\n\nWhen ``conversation_id`` is supplied, the memory is also linked\nto every node cited by any message in that conversation — those\nare the workspace nodes the prompt run produced or referenced\nwhile answering, so the memory's ``memory_about`` edges cover\nthe full graph footprint of the chat session, not just whatever\nthe caller explicitly listed.","operationId":"create_memory_route_v1_memories_post","parameters":[{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Workspace to create the memory in; defaults to the user's default workspace.","title":"Workspace Id"},"description":"Workspace to create the memory in; defaults to the user's default workspace."}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"description":"Body for POST /memories.","properties":{"title":{"description":"Short label for the memory (≤200 chars).","maxLength":200,"minLength":1,"title":"Title","type":"string"},"content":{"default":"","description":"Free-form writeup of the work and its result. Markdown is welcome; up to 8000 characters.","maxLength":8000,"title":"Content","type":"string"},"related_node_ids":{"description":"Workspace node ids the memory is about. Each gets a ``memory_about`` edge from the new memory node so future graph reads of those nodes surface the memory.","items":{"format":"uuid","type":"string"},"maxItems":32,"title":"Related Node Ids","type":"array"},"kind":{"default":"manual","description":"Why the memory was written. ``manual`` for UI / REST, ``agent_run`` for agent-tool authored memories.","pattern":"^[a-z][a-z0-9_]{0,31}$","title":"Kind","type":"string"},"agent_id":{"anyOf":[{"maxLength":128,"type":"string"},{"type":"null"}],"description":"String tag of the writing agent, if applicable.","title":"Agent Id"},"conversation_id":{"anyOf":[{"format":"uuid","type":"string"},{"type":"null"}],"description":"Conversation that produced the memory, if any.","title":"Conversation Id"},"tags":{"description":"Optional free-form tag list (≤16 entries).","items":{"type":"string"},"maxItems":16,"title":"Tags","type":"array"}},"required":["title"],"title":"MemoryCreateRequest","type":"object"}}}}},"get":{"tags":["memories"],"summary":"List Memories Route","description":"List memories in the caller's workspace, most recent first.","operationId":"list_memories_route_v1_memories_get","parameters":[{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Workspace Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MemoryResponse"},"title":"Response List Memories Route V1 Memories Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memories/recall":{"get":{"tags":["memories"],"summary":"Recall Memories Route","description":"Return memories adjacent to the supplied workspace nodes.","operationId":"recall_memories_route_v1_memories_recall_get","parameters":[{"name":"node_ids","in":"query","required":false,"schema":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Workspace node ids to recall memories for. Returns memories whose ``memory_about`` edges target any of these nodes.","title":"Node Ids"},"description":"Workspace node ids to recall memories for. Returns memories whose ``memory_about`` edges target any of these nodes."},{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Workspace Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":25,"minimum":1,"default":6,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MemoryResponse"},"title":"Response Recall Memories Route V1 Memories Recall Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memories/{memory_id}":{"get":{"tags":["memories"],"summary":"Get Memory Route","description":"Fetch one memory by id.","operationId":"get_memory_route_v1_memories__memory_id__get","parameters":[{"name":"memory_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Memory Id"}},{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/memories/{memory_id}/attach":{"post":{"tags":["memories"],"summary":"Attach Memory Route","description":"Add additional ``memory_about`` edges to an existing memory.","operationId":"attach_memory_route_v1_memories__memory_id__attach_post","parameters":[{"name":"memory_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Memory Id"}},{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Workspace Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryAttachRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/memory/list":{"get":{"tags":["memory-workbench"],"summary":"List Memories Endpoint","description":"Return a paginated cross-kind memory list.\n\nArgs:\n    workspace_id: Target workspace UUID (path param).\n    kinds: Optional filter list.\n    pinned_only: Return only pinned items.\n    edited_only: Return only operator-touched items.\n    q: Case-insensitive title substring filter.\n    sort: Sort order key.\n    limit: Page size (max 200).\n    cursor: Continuation token from a previous response.\n    current_user: JWT-verified caller.\n    session: RLS-scoped session.\n\nReturns:\n    Envelope with items and optional next_cursor.","operationId":"list_memories_endpoint_v1_workspaces__workspace_id__memory_list_get","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"kinds","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Kinds"}},{"name":"pinned_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Pinned Only"}},{"name":"edited_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Edited Only"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","default":"effective_weight_desc","title":"Sort"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/memory/items/{memory_id}":{"get":{"tags":["memory-workbench"],"summary":"Get Memory Detail Endpoint","description":"Return the fully resolved detail for one memory node.\n\nArgs:\n    workspace_id: Target workspace UUID.\n    memory_id: UUID of the memory node.\n    current_user: JWT-verified caller.\n    session: RLS-scoped session.\n\nReturns:\n    MemoryDetailResponse with kind, scores, pin state, and fields.\n\nRaises:\n    HTTPException: 404 if the memory does not exist or is deleted.","operationId":"get_memory_detail_endpoint_v1_workspaces__workspace_id__memory_items__memory_id__get","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"memory_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Memory Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemoryDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["memory-workbench"],"summary":"Delete Memory","description":"Forget (delete) a memory node.\n\nChecks the pin guard: pinned nodes require require_grant=true to\ndelete.\n\nArgs:\n    workspace_id: Target workspace UUID.\n    memory_id: UUID of the memory node.\n    require_grant: When True, bypasses the pin guard.\n    current_user: JWT-verified caller.\n    session: RLS-scoped session.\n\nReturns:\n    Confirmation dict.\n\nRaises:\n    HTTPException: 404 if memory does not exist.\n    HTTPException: 403 if pinned and require_grant is False.","operationId":"delete_memory_v1_workspaces__workspace_id__memory_items__memory_id__delete","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"memory_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Memory Id"}},{"name":"require_grant","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Require Grant"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Memory V1 Workspaces  Workspace Id  Memory Items  Memory Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/memory/items/{memory_id}/weight":{"patch":{"tags":["memory-workbench"],"summary":"Patch Weight","description":"Set or update the operator weight for a memory node.\n\nArgs:\n    workspace_id: Target workspace UUID.\n    memory_id: UUID of the memory node.\n    body: Weight value and audit reason.\n    current_user: JWT-verified caller.\n    session: RLS-scoped session.\n\nReturns:\n    WeightResponse with persisted weight and reason.\n\nRaises:\n    HTTPException: 404 if memory does not exist.\n    HTTPException: 422 on weight out of range or empty reason.","operationId":"patch_weight_v1_workspaces__workspace_id__memory_items__memory_id__weight_patch","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"memory_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Memory Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WeightPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WeightResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/memory/items/{memory_id}/pin":{"post":{"tags":["memory-workbench"],"summary":"Pin Memory","description":"Pin a memory node to prevent eviction.\n\nArgs:\n    workspace_id: Target workspace UUID.\n    memory_id: UUID of the memory node.\n    body: Audit reason for pinning.\n    current_user: JWT-verified caller.\n    session: RLS-scoped session.\n\nReturns:\n    PinResponse with is_pinned=True.\n\nRaises:\n    HTTPException: 404 if memory does not exist.","operationId":"pin_memory_v1_workspaces__workspace_id__memory_items__memory_id__pin_post","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"memory_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Memory Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PinBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PinResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["memory-workbench"],"summary":"Unpin Memory","description":"Remove the pin from a memory node.\n\nArgs:\n    workspace_id: Target workspace UUID.\n    memory_id: UUID of the memory node.\n    current_user: JWT-verified caller.\n    session: RLS-scoped session.\n\nReturns:\n    PinResponse with is_pinned=False.\n\nRaises:\n    HTTPException: 404 if memory does not exist.","operationId":"unpin_memory_v1_workspaces__workspace_id__memory_items__memory_id__pin_delete","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"memory_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Memory Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PinResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/memory/procedures/{procedure_id}":{"patch":{"tags":["memory-workbench"],"summary":"Edit Procedure Endpoint","description":"Edit a procedure node's trigger, instruction, or suppression.\n\nAppends an immutable ProcedureRevision audit row for each change.\n\nArgs:\n    workspace_id: Target workspace UUID.\n    procedure_id: UUID of the memory.procedure node.\n    body: Optional trigger_pattern, instruction, suppressed.\n    current_user: JWT-verified caller.\n    session: RLS-scoped session.\n\nReturns:\n    Dict with revision_id and procedure_id.\n\nRaises:\n    HTTPException: 404 if procedure does not exist.","operationId":"edit_procedure_endpoint_v1_workspaces__workspace_id__memory_procedures__procedure_id__patch","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"procedure_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Procedure Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcedureEditBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Edit Procedure Endpoint V1 Workspaces  Workspace Id  Memory Procedures  Procedure Id  Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/memory/patterns/{pattern_id}/promote":{"post":{"tags":["memory-workbench"],"summary":"Promote Pattern Endpoint","description":"Promote an AgentPattern to a memory.procedure node.\n\nArgs:\n    workspace_id: Target workspace UUID.\n    pattern_id: Primary key of the AgentPattern row.\n    current_user: JWT-verified caller.\n    session: RLS-scoped session.\n\nReturns:\n    Dict with new procedure_id.\n\nRaises:\n    HTTPException: 404 if pattern does not exist.","operationId":"promote_pattern_endpoint_v1_workspaces__workspace_id__memory_patterns__pattern_id__promote_post","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"pattern_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Pattern Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Promote Pattern Endpoint V1 Workspaces  Workspace Id  Memory Patterns  Pattern Id  Promote Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/memory/adhoc":{"post":{"tags":["memory-workbench"],"summary":"Create Adhoc Memory Endpoint","description":"Create an ad-hoc operator-authored memory.\n\nArgs:\n    workspace_id: Target workspace UUID.\n    body: Trigger (\"when should agents use this memory?\") and\n        memory text.\n    current_user: JWT-verified caller.\n    session: RLS-scoped session.\n\nReturns:\n    Dict with the new memory_id and kind.","operationId":"create_adhoc_memory_endpoint_v1_workspaces__workspace_id__memory_adhoc_post","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdhocCreateBody"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Adhoc Memory Endpoint V1 Workspaces  Workspace Id  Memory Adhoc Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/memory/adhoc/{memory_id}":{"patch":{"tags":["memory-workbench"],"summary":"Edit Adhoc Memory Endpoint","description":"Edit an ad-hoc memory's trigger, memory text, or suppression.\n\nArgs:\n    workspace_id: Target workspace UUID.\n    memory_id: UUID of the ``memory.adhoc`` node.\n    body: Optional trigger / memory / suppressed.\n    current_user: JWT-verified caller.\n    session: RLS-scoped session.\n\nReturns:\n    Confirmation dict with memory_id.\n\nRaises:\n    HTTPException: 404 if not found, 422 on validation error.","operationId":"edit_adhoc_memory_endpoint_v1_workspaces__workspace_id__memory_adhoc__memory_id__patch","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"memory_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Memory Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdhocEditBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Edit Adhoc Memory Endpoint V1 Workspaces  Workspace Id  Memory Adhoc  Memory Id  Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/memory/procedures/{procedure_id}/demote":{"post":{"tags":["memory-workbench"],"summary":"Demote Procedure Endpoint","description":"Demote a memory.procedure node back to an AgentPattern row.\n\nArgs:\n    workspace_id: Target workspace UUID.\n    procedure_id: UUID of the memory.procedure node.\n    current_user: JWT-verified caller.\n    session: RLS-scoped session.\n\nReturns:\n    Dict with new pattern_id.\n\nRaises:\n    HTTPException: 404 if procedure does not exist.","operationId":"demote_procedure_endpoint_v1_workspaces__workspace_id__memory_procedures__procedure_id__demote_post","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"procedure_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Procedure Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Demote Procedure Endpoint V1 Workspaces  Workspace Id  Memory Procedures  Procedure Id  Demote Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/memory/benchmarks":{"get":{"tags":["memory-workbench"],"summary":"List Benchmarks","description":"Return the latest benchmark rollup rows for the workspace.\n\nReturns the most recent :class:`AgentBenchmark` row per metric\ndefinition for the requested aggregation window.  Results are\nordered by ``created_at`` descending.\n\nArgs:\n    workspace_id: Target workspace UUID (path param).\n    window: Aggregation window key -- one of ``24h``, ``7d``,\n        ``30d``.\n    metric: Optional metric name filter.\n    limit: Maximum number of rows to return (max 200).\n    current_user: JWT-verified caller.\n    session: RLS-scoped session.\n\nReturns:\n    BenchmarksResponse envelope with matching benchmark rows.\n\nRaises:\n    HTTPException: 404 if workspace not found or inaccessible.\n    HTTPException: 422 if ``window`` is not a valid key.","operationId":"list_benchmarks_v1_workspaces__workspace_id__memory_benchmarks_get","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"window","in":"query","required":false,"schema":{"type":"string","description":"Aggregation window: 24h, 7d, or 30d.","default":"24h","title":"Window"},"description":"Aggregation window: 24h, 7d, or 30d."},{"name":"metric","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by metric name (e.g. success_rate).","title":"Metric"},"description":"Filter by metric name (e.g. success_rate)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchmarksResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/financial/expense-reports/{trip_id}/generate":{"post":{"tags":["financial"],"summary":"Generate Expense Report","description":"Assemble and return an :class:`ExpenseReport` for ``trip_id``.\n\nArgs:\n    trip_id: UUID of the ``financial.trip`` node to summarise.\n    user: Authenticated caller — workspace scope is the caller's\n        default workspace.\n    session: RLS-bound workspace session.\n\nReturns:\n    Fully-populated :class:`ExpenseReport`.\n\nRaises:\n    HTTPException: 404 if the trip node is not found in the\n        caller's workspace; 404 if the caller has no default\n        workspace.","operationId":"generate_expense_report_v1_financial_expense_reports__trip_id__generate_post","parameters":[{"name":"trip_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Trip Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpenseReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/financial/expense-reports/{trip_id}.pdf":{"get":{"tags":["financial"],"summary":"Stream Expense Report Pdf","description":"Render the expense report as an ``application/pdf`` payload.\n\nArgs:\n    trip_id: UUID of the ``financial.trip`` node.\n    user: Authenticated caller.\n    session: RLS-bound workspace session.\n\nReturns:\n    :class:`fastapi.Response` with the PDF bytes and a\n    ``Content-Disposition: attachment`` header naming the file\n    after the trip.\n\nRaises:\n    HTTPException: 404 if the trip is missing; 503 if the PDF\n        renderer dependency isn't installed in this environment.","operationId":"stream_expense_report_pdf_v1_financial_expense_reports__trip_id__pdf_get","parameters":[{"name":"trip_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Trip Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/models/eligibility":{"get":{"tags":["workspace-models"],"summary":"Get Eligibility","description":"Report whether the current plan grants BYOK to this workspace.\n\nArgs:\n    workspace_id: Target workspace.\n    user: Authenticated caller (any workspace member).\n    session: RLS-scoped session.\n\nReturns:\n    :class:`EligibilityResponse` so the UI can render either the\n    credential manager or an upgrade CTA without a second\n    round-trip to the billing service.","operationId":"get_eligibility_v1_workspaces__workspace_id__models_eligibility_get","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EligibilityResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/models/credentials":{"get":{"tags":["workspace-models"],"summary":"List Workspace Credentials","description":"List BYOK credentials for a workspace (metadata only — no secrets).\n\nArgs:\n    workspace_id: Target workspace.\n    user: Authenticated workspace member.\n    session: RLS-scoped session.\n\nReturns:\n    The list of active credentials with key previews + health.","operationId":"list_workspace_credentials_v1_workspaces__workspace_id__models_credentials_get","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["workspace-models"],"summary":"Create Workspace Credential","description":"Validate + persist a new BYOK credential.\n\nArgs:\n    workspace_id: Target workspace.\n    body: Request payload (provider, label, api_key).\n    user: Authenticated tenant OWNER.\n    session: RLS-scoped session.\n\nReturns:\n    The created credential (metadata only, no secret).\n\nRaises:\n    HTTPException: 403 if user is not an owner, or plan is not\n        BYOK-eligible; 422 if the provider rejects the supplied\n        key.","operationId":"create_workspace_credential_v1_workspaces__workspace_id__models_credentials_post","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCredentialRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/models/credentials/{cred_id}":{"delete":{"tags":["workspace-models"],"summary":"Delete Workspace Credential","description":"Soft-delete a workspace credential.\n\nArgs:\n    workspace_id: Target workspace.\n    cred_id: Credential to soft-delete.\n    user: Authenticated tenant OWNER.\n    session: RLS-scoped session.\n\nRaises:\n    HTTPException: 403 if user is not an owner; 404 if the\n        credential is not found.","operationId":"delete_workspace_credential_v1_workspaces__workspace_id__models_credentials__cred_id__delete","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"cred_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cred Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/models/credentials/{cred_id}/test":{"post":{"tags":["workspace-models"],"summary":"Test Workspace Credential","description":"Re-run the provider validation probe on a stored credential.\n\nOwner-only: a re-test consumes one billable request on the\ncustomer's provider account (one Anthropic 1-token completion\nor one OpenAI embedding). Restricting to the tenant OWNER\nprevents non-owner members from quietly racking up probe calls\nagainst the owner's billed-of-record account.\n\nArgs:\n    workspace_id: Target workspace.\n    cred_id: Credential to re-test.\n    user: Authenticated tenant OWNER.\n    session: RLS-scoped session.\n\nReturns:\n    The refreshed credential with updated ``health_status`` /\n    ``health_error`` / ``last_health_check_at``.\n\nRaises:\n    HTTPException: 403 if user is not an owner; 404 if the\n        credential is missing.","operationId":"test_workspace_credential_v1_workspaces__workspace_id__models_credentials__cred_id__test_post","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"cred_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cred Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspace-models/catalog":{"get":{"tags":["workspace-models"],"summary":"Model catalog for this workspace","description":"Return the full model catalog annotated for this workspace.\n\nFilters nothing — every non-deprecated model is returned. Each\nentry carries ``byok_required`` (True when no credential exists for\nthat provider) and ``pro_required`` (True when the model needs Pro).\nThe UI uses this single endpoint for both the workspace Models tab\ndropdowns and the chat composer picker.\n\nArgs:\n    workspace_id: Target workspace UUID.\n    user: Authenticated workspace member.\n    session: RLS-scoped session.\n\nReturns:\n    :class:`CatalogResponse` with all models and the current plan.","operationId":"get_model_catalog_v1_workspace_models_catalog_get","parameters":[{"name":"workspace_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Target workspace. Only models accessible to this workspace (BYOK keys + plan eligibility) are annotated correctly.","title":"Workspace Id"},"description":"Target workspace. Only models accessible to this workspace (BYOK keys + plan eligibility) are annotated correctly."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspace-models/workspace/model-config":{"patch":{"tags":["workspace-models"],"summary":"Atomic replace of workspace model config","description":"Atomically replace the workspace model config.\n\nValidates that every non-``\"oxagen-managed\"`` value is a known\nmodel ID in the registry. Returns 422 on the first unknown model.\nThe ``embedding`` field is stored but not yet consumed by the\nresolver (embeddings override lands in Wave 6).\n\nArgs:\n    body: New model config. All four fields are optional; omitted\n        fields default to ``\"oxagen-managed\"``.\n    workspace_id: Target workspace UUID.\n    user: Authenticated tenant OWNER.\n    session: RLS-scoped session.\n\nReturns:\n    ``{\"ok\": True, \"model_config\": {...}}`` on success.\n\nRaises:\n    HTTPException: 403 if user is not the tenant owner; 404 if the\n        workspace is not found; 422 if an unknown model ID is given.","operationId":"update_workspace_model_config_v1_workspace_models_workspace_model_config_patch","parameters":[{"name":"workspace_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Target workspace UUID.","title":"Workspace Id"},"description":"Target workspace UUID."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelConfigUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Workspace Model Config V1 Workspace Models Workspace Model Config Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/agents":{"get":{"tags":["agents"],"summary":"List agent definitions for a workspace","description":"List all active agent definitions for a workspace.\n\nArgs:\n    workspace_id: Target workspace.\n    user: Authenticated workspace member.\n    session: RLS-scoped session.\n\nReturns:\n    List of :class:`AgentResponse`, newest first.","operationId":"list_agents_v1_agents_get","parameters":[{"name":"workspace_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Target workspace UUID.","title":"Workspace Id"},"description":"Target workspace UUID."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AgentResponse"},"title":"Response List Agents V1 Agents Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["agents"],"summary":"Create a new agent definition","description":"Create a new agent definition.\n\nArgs:\n    body: Agent definition payload.\n    workspace_id: Target workspace.\n    user: Authenticated caller.\n    session: RLS-scoped session.\n\nReturns:\n    The created :class:`AgentResponse`.\n\nRaises:\n    HTTPException: 422 for invalid tier or model_id.","operationId":"create_agent_v1_agents_post","parameters":[{"name":"workspace_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Target workspace UUID.","title":"Workspace Id"},"description":"Target workspace UUID."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/agents/{agent_id}":{"get":{"tags":["agents"],"summary":"Get a single agent definition","description":"Get a single agent definition by ID.\n\nArgs:\n    agent_id: Agent definition UUID.\n    workspace_id: Optional workspace pin.\n    user: Authenticated caller.\n    session: RLS-scoped session.\n\nReturns:\n    :class:`AgentResponse` for the agent.\n\nRaises:\n    HTTPException: 404 when not found.","operationId":"get_agent_v1_agents__agent_id__get","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Agent Id"}},{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["agents"],"summary":"Update an agent definition","description":"Update fields on an agent definition.\n\nPartial update — unset fields keep their previous values.\n``default_tier`` and ``default_model_id`` are validated against\nthe registry. Passing ``default_model_id=''`` clears the model\noverride and falls back to ``default_tier``.\n\nArgs:\n    agent_id: Agent UUID.\n    body: Partial update payload.\n    workspace_id: Optional workspace pin for validation.\n    user: Authenticated caller.\n    session: RLS-scoped session.\n\nReturns:\n    The updated :class:`AgentResponse`.\n\nRaises:\n    HTTPException: 404 when the agent is not found or is builtin;\n        422 for invalid tier or model_id.","operationId":"update_agent_v1_agents__agent_id__patch","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Agent Id"}},{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Workspace Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["agents"],"summary":"Soft-delete an agent definition","description":"Soft-delete an agent definition.\n\nArgs:\n    agent_id: Agent UUID.\n    workspace_id: Optional workspace pin.\n    user: Authenticated caller.\n    session: RLS-scoped session.\n\nRaises:\n    HTTPException: 404 when not found; 403 when builtin.","operationId":"delete_agent_v1_agents__agent_id__delete","parameters":[{"name":"agent_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Agent Id"}},{"name":"workspace_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Workspace Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/content-studio/runs":{"post":{"tags":["Content Studio"],"summary":"Create Run Route","description":"Create a :class:`GenerationRun` and dispatch the Celery worker.\n\nCredit gate: ``content_studio.generate`` fires before the row is\npersisted, so a zero-balance tenant is rejected with 402 before any\nstate is written.\n\nDispatches ``worker.tasks.content_studio.generate_content_task``\nafter the commit via\n:func:`app.worker_bus.dispatch_content_studio_generate`.\nA broker blip is logged at ERROR but does **not** fail the request\n(the run row persists in PENDING; a future retry endpoint can\nre-dispatch — OXA-993 follow-up).\n\nAgent callers (service-account JWTs and MCP callers) MUST pass\n``visibility_confirmed=true`` when requesting a PUBLIC run.\nInteractive (human) callers may omit the flag; the UI handles\nthe confirmation dialogue client-side.\n\nFor ``visibility=PUBLIC`` runs a governance audit row is written\nafter dispatch so the audit trail reflects the data-externalisation\ndecision.\n\nArgs:\n    workspace_id: Owning workspace UUID (path parameter).\n    request: Raw FastAPI request — body is decoded inside.\n    receipt: Credit reservation (consumed by dependency).\n    user: Authenticated caller.\n    session: Workspace-scoped DB session.\n\nReturns:\n    202 Accepted with the new run in ``PENDING`` status.","operationId":"create_run_route_v1_workspaces__workspace_id__content_studio_runs_post","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$defs":{"GenerationOutputType":{"description":"Requested artifact type for a generation run.\n\nA single run may request multiple types (the runtime fans out\nasset generation in parallel), so the runs table stores a\nJSONB array of these values rather than a single column.","enum":["video","audio","infographic"],"title":"GenerationOutputType","type":"string"},"GenerationVisibility":{"description":"Who can view a finished generation run.\n\n- ``WORKSPACE`` (default) — only members of the owning tenant\n  can view, via authenticated UI / API.\n- ``PUBLIC`` — anyone holding the run's ``share_token`` can\n  view via the unauthenticated public viewer route. Mirrors\n  Google Docs \"anyone with the link\" sharing. Tenant owners\n  revoke by stamping ``share_revoked_at``.\n\nThe agent that creates a run MUST ask the user which scope\napplies before rendering — public is never a silent default\nbecause it inverts the tenant data-isolation invariant.","enum":["workspace","public"],"title":"GenerationVisibility","type":"string"}},"description":"Payload for ``POST /workspaces/{id}/content-studio/runs``.\n\nValidation rules:\n\n- ``prompt`` must be non-empty after stripping whitespace.\n- ``output_types`` must contain at least one entry.\n- ``target_duration_seconds`` is clamped to\n  ``[MIN_DURATION_SECONDS, MAX_DURATION_SECONDS]`` on the\n  server side — clients may send any value.","properties":{"prompt":{"description":"Natural-language ask, e.g. '10-minute onboarding video for new engineers'.","maxLength":8000,"minLength":1,"title":"Prompt","type":"string"},"output_types":{"description":"Requested artifact types. The worker fans out asset generation in parallel.","items":{"$ref":"#/components/schemas/GenerationOutputType"},"minItems":1,"title":"Output Types","type":"array"},"target_duration_seconds":{"default":600,"description":"Desired runtime in seconds. Server clamps to [60, 600]. Ignored for infographic-only runs.","minimum":1,"title":"Target Duration Seconds","type":"integer"},"template_id":{"anyOf":[{"maxLength":64,"type":"string"},{"type":"null"}],"description":"Remotion template identifier. Defaults to 'onboarding' when video is requested and no value is supplied.","title":"Template Id"},"visibility":{"$ref":"#/components/schemas/GenerationVisibility","default":"workspace","description":"WORKSPACE keeps the run visible only to authenticated members of the owning tenant. PUBLIC mints an unguessable share token so anyone holding the URL can watch the finished video. The calling agent MUST confirm with the user before setting PUBLIC."},"visibility_confirmed":{"default":false,"description":"Required when ``visibility=PUBLIC`` AND the caller is an agent (service-account or MCP JWT). The API rejects agent-initiated PUBLIC runs with 400 when this flag is not explicitly set to ``true``. Human-originated requests (interactive JWT) may omit this field. Prevents silent public disclosure from an agent acting without user consent.","title":"Visibility Confirmed","type":"boolean"}},"required":["prompt","output_types"],"title":"CreateRunRequest","type":"object"}}}}},"get":{"tags":["Content Studio"],"summary":"List Runs Route","description":"List recent runs for the workspace, newest first.\n\nThe response is wrapped in a paginated envelope (``items`` +\n``next_cursor``) to match the TS client contract. Cursor pagination\nis not yet implemented in the service layer, so ``next_cursor``\nis always ``None`` — the first 50 rows are returned in one page.\n\nArgs:\n    workspace_id: Owning workspace UUID.\n    user: Authenticated caller.\n    session: Workspace-scoped DB session.\n\nReturns:\n    Page of up to 50 runs ordered by ``created_at`` DESC.","operationId":"list_runs_route_v1_workspaces__workspace_id__content_studio_runs_get","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/content-studio/runs/trash":{"get":{"tags":["Content Studio"],"summary":"List Trash Route","description":"List soft-deleted runs for the recycle bin.","operationId":"list_trash_route_v1_workspaces__workspace_id__content_studio_runs_trash_get","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/content-studio/runs/{run_id}":{"get":{"tags":["Content Studio"],"summary":"Get Run Route","description":"Return a single :class:`GenerationRun` by ID.\n\nArgs:\n    workspace_id: Owning workspace UUID (unused directly; RLS\n        enforces scope).\n    run_id: Run UUID.\n    user: Authenticated caller.\n    session: Workspace-scoped DB session.\n\nReturns:\n    Serialised run.\n\nRaises:\n    HTTPException: 404 when the run is absent or inaccessible.","operationId":"get_run_route_v1_workspaces__workspace_id__content_studio_runs__run_id__get","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Content Studio"],"summary":"Delete Run Route","description":"Soft-delete a generation run (recycle bin).","operationId":"delete_run_route_v1_workspaces__workspace_id__content_studio_runs__run_id__delete","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/content-studio/runs/{run_id}/stream":{"get":{"tags":["Content Studio"],"summary":"Stream Run Route","description":"Stream progress events for a :class:`GenerationRun` via SSE.\n\nSubscribes to the Redis Pub/Sub channel\n``content_studio:run:{run_id}`` and forwards events as\nServer-Sent Events.  Falls back to DB polling when Redis is\nunavailable.\n\nEvent types:\n\n- ``progress`` — intermediate status update (``running``).\n- ``done`` — terminal success (``succeeded``).\n- ``error`` — terminal failure (``failed`` / ``cancelled``).\n\nArgs:\n    workspace_id: Owning workspace UUID (RLS enforces scope).\n    run_id: Run UUID to stream progress for.\n    request: FastAPI request (client-disconnect detection).\n    user: Authenticated caller.\n    session: Workspace-scoped DB session (used for initial\n        existence check only).\n\nReturns:\n    ``StreamingResponse`` with ``Content-Type: text/event-stream``.\n\nRaises:\n    HTTPException: 404 when the run does not exist or is\n        inaccessible to the caller.","operationId":"stream_run_route_v1_workspaces__workspace_id__content_studio_runs__run_id__stream_get","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/content-studio/runs/{run_id}/revoke-share":{"patch":{"tags":["Content Studio"],"summary":"Revoke Share Route","description":"Revoke the public share link for a generation run.\n\nOnly the owner of the run (the user who created it) may revoke\nthe public link. The artifact stays accessible to workspace\nmembers; only the unauthenticated public viewer returns 410 Gone\nfor the share token going forward.\n\nIdempotent: revoking an already-revoked run is a no-op.\n\nAlso writes a governance audit row with\n``action='content_studio.revoke_public'`` so compliance tooling\ncan track the change.\n\nArgs:\n    workspace_id: Owning workspace.\n    run_id: ID of the :class:`GenerationRun` to revoke.\n    user: Authenticated requesting user.\n    session: Workspace-scoped session.\n\nReturns:\n    Updated :class:`RunResponse` with ``share_revoked=True``.\n\nRaises:\n    HTTPException: 404 if the run is not found, 403 if the\n        caller is not the run owner, 400 if the run is not\n        PUBLIC.","operationId":"revoke_share_route_v1_workspaces__workspace_id__content_studio_runs__run_id__revoke_share_patch","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/content-studio/runs/{run_id}/restore":{"post":{"tags":["Content Studio"],"summary":"Restore Run Route","description":"Restore a soft-deleted run from the recycle bin.","operationId":"restore_run_route_v1_workspaces__workspace_id__content_studio_runs__run_id__restore_post","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/workspaces/{workspace_id}/content-studio/runs/{run_id}/purge":{"delete":{"tags":["Content Studio"],"summary":"Purge Run Route","description":"Permanently delete a run already in the recycle bin.","operationId":"purge_run_route_v1_workspaces__workspace_id__content_studio_runs__run_id__purge_delete","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AdhocCreateBody":{"properties":{"trigger":{"type":"string","maxLength":500,"minLength":1,"title":"Trigger"},"memory":{"type":"string","maxLength":4000,"minLength":1,"title":"Memory"}},"type":"object","required":["trigger","memory"],"title":"AdhocCreateBody","description":"Body for POST /workspaces/{workspace_id}/memory/adhoc.\n\nAttributes:\n    trigger: \"When should agents use this memory?\" — 1-500 chars.\n    memory: The memory text agents should reference when the\n        trigger matches — 1-4000 chars."},"AdhocEditBody":{"properties":{"trigger":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trigger"},"memory":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Memory"},"suppressed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Suppressed"}},"type":"object","title":"AdhocEditBody","description":"Body for PATCH /workspaces/{workspace_id}/memory/adhoc/{id}.\n\nAttributes:\n    trigger: Replacement trigger or ``None`` to leave unchanged.\n    memory: Replacement memory text or ``None``.\n    suppressed: Replacement suppressed flag or ``None``."},"AgentClaimWorkInput":{"properties":{"session_id":{"type":"string","format":"uuid","title":"Session Id","description":"UUID of the active ``agent.session`` opening this claim. Must be active and owned by the JWT-derived caller."},"target_node_id":{"type":"string","format":"uuid","title":"Target Node Id","description":"UUID of the node being claimed. Typically a ``code.*`` node (file / function / class), but any node in the caller's workspace is accepted."},"intent":{"type":"string","maxLength":512,"minLength":1,"title":"Intent","description":"Short description of what the agent intends to do with the target. Required, non-empty."}},"additionalProperties":false,"type":"object","required":["session_id","target_node_id","intent"],"title":"AgentClaimWorkInput","description":"Input for ``agent.claim_work``."},"AgentClaimWorkOutput":{"properties":{"claim_id":{"type":"string","format":"uuid","title":"Claim Id","description":"UUID of the ``agent.claim`` node."},"platform_claim_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Platform Claim Id","description":"UUID of the ``run.work_claim`` Postgres row, when the call was made in a platform run context. Pass this to ``agent.release_claim`` as ``platform_claim_id`` so the Postgres row can be released independently from the Neo4j claim node."},"session_id":{"type":"string","format":"uuid","title":"Session Id","description":"UUID of the owning session."},"target_node_id":{"type":"string","format":"uuid","title":"Target Node Id","description":"UUID of the claimed target node."},"intent":{"type":"string","title":"Intent","description":"Intent text stored on the claim."},"status":{"type":"string","title":"Status","description":"Claim status — always ``'active'`` at creation."}},"type":"object","required":["claim_id","session_id","target_node_id","intent","status"],"title":"AgentClaimWorkOutput","description":"Projection of a created or updated claim node."},"AgentCreate":{"properties":{"slug":{"type":"string","maxLength":120,"pattern":"^[a-z0-9_-]+$","title":"Slug","description":"Lowercase machine identifier (``[a-z0-9_-]+``)."},"name":{"type":"string","maxLength":200,"title":"Name","description":"Human-facing name."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Optional long-form description."},"system_prompt_md":{"type":"string","title":"System Prompt Md","description":"System prompt body (markdown)."},"allowed_capability_globs":{"items":{"type":"string"},"type":"array","title":"Allowed Capability Globs","description":"Capability globs the agent is permitted to invoke."},"denied_capability_globs":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Denied Capability Globs","description":"Capability globs explicitly denied."},"default_tier":{"type":"string","title":"Default Tier","description":"Model tier. One of ``'level_1'``, ``'level_2'``, ``'level_3'``.","default":"level_1"},"default_model_id":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Default Model Id","description":"Optional explicit model override. Wins over ``default_tier`` when set. Must exist in the registry."},"step_budget":{"type":"integer","title":"Step Budget","default":30},"credit_budget":{"type":"integer","title":"Credit Budget","default":200}},"type":"object","required":["slug","name","system_prompt_md"],"title":"AgentCreate","description":"Body for POST /agents."},"AgentEndSessionInput":{"properties":{"session_id":{"type":"string","format":"uuid","title":"Session Id","description":"UUID of the ``agent.session`` node to end."},"outcome":{"type":"string","enum":["succeeded","failed","abandoned"],"title":"Outcome","description":"Final outcome of the session. Drives the M8 promotion pipeline's cluster anchor. ``failed`` requires ``error_signature`` for the cluster to form.","default":"succeeded"},"error_signature":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Error Signature","description":"Stable, normalised error string when ``outcome='failed'``. Required for SPEC §6.2 failure clusters."},"summary":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Summary","description":"Optional short summary of what the session did. Stamped on the graph Episode for recall and audit."}},"additionalProperties":false,"type":"object","required":["session_id"],"title":"AgentEndSessionInput","description":"Input for ``agent.end_session``."},"AgentEndSessionOutput":{"properties":{"session_id":{"type":"string","format":"uuid","title":"Session Id","description":"UUID of the session that was ended."},"status":{"type":"string","title":"Status","description":"Final status — ``'ended'`` after a real end, the previous terminal status when idempotent."},"claims_abandoned":{"type":"integer","title":"Claims Abandoned","description":"Number of active claims cascaded to ``'abandoned'``. Zero on an idempotent call."},"already_ended":{"type":"boolean","title":"Already Ended","description":"``True`` when the session was already in a terminal state before this call."}},"type":"object","required":["session_id","status","claims_abandoned","already_ended"],"title":"AgentEndSessionOutput","description":"Result of ending a session."},"AgentGetFindingsInput":{"properties":{"target_node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Target Node Id","description":"Restrict to findings targeting this ``code.*`` node. When set, uses the SQL-pushed exhaustive lookup."},"severity":{"anyOf":[{"type":"string","enum":["critical","high","medium","low","info"]},{"type":"null"}],"title":"Severity","description":"Restrict to a single severity tier (post-filter over the target query result)."},"limit":{"type":"integer","maximum":1000.0,"minimum":1.0,"title":"Limit","description":"Maximum findings to return. Default 100, max 1000.","default":100}},"additionalProperties":false,"type":"object","title":"AgentGetFindingsInput","description":"Input for ``agent.get_findings``."},"AgentGetFindingsOutput":{"properties":{"findings":{"items":{"$ref":"#/components/schemas/FindingItem"},"type":"array","title":"Findings","description":"Matching finding nodes, ordered by ``created_at``."},"total":{"type":"integer","title":"Total","description":"Number of findings returned (≤ limit)."}},"type":"object","required":["total"],"title":"AgentGetFindingsOutput","description":"Finding list response."},"AgentHeartbeatInput":{"properties":{"session_id":{"type":"string","format":"uuid","title":"Session Id","description":"UUID of the ``agent.session`` node to heartbeat."}},"additionalProperties":false,"type":"object","required":["session_id"],"title":"AgentHeartbeatInput","description":"Input for ``agent.heartbeat``."},"AgentHeartbeatOutput":{"properties":{"session_id":{"type":"string","format":"uuid","title":"Session Id","description":"UUID of the session that was heartbeated."},"status":{"type":"string","title":"Status","description":"Current session status. ``'active'`` when the heartbeat landed; ``'ended'`` or ``'abandoned'`` when the session is no longer active."},"last_heartbeat_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Heartbeat At","description":"ISO-8601 timestamp of the latest heartbeat (UTC)."},"already_inactive":{"type":"boolean","title":"Already Inactive","description":"``True`` when the session was not active — no heartbeat was applied. The caller should stop heartbeating.","default":false}},"type":"object","required":["session_id","status"],"title":"AgentHeartbeatOutput","description":"Heartbeat acknowledgement."},"AgentListActiveClaimsInput":{"properties":{"session_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Session Id","description":"Restrict to claims owned by this session. Uses ``list_active_claims_for_session`` (SQL-pushed, exhaustive)."},"target_node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Target Node Id","description":"Restrict to the active claim on this target node. Uses ``list_active_claims_for_target`` (SQL-pushed, exhaustive)."}},"additionalProperties":false,"type":"object","title":"AgentListActiveClaimsInput","description":"Input for ``agent.list_active_claims``."},"AgentListActiveClaimsOutput":{"properties":{"claims":{"items":{"$ref":"#/components/schemas/ClaimItem"},"type":"array","title":"Claims","description":"Active claim nodes matching the filters."},"total":{"type":"integer","title":"Total","description":"Number of claims returned."}},"type":"object","required":["total"],"title":"AgentListActiveClaimsOutput","description":"Active claims list response."},"AgentReadDecisionsInput":{"properties":{"run_id":{"type":"string","format":"uuid","title":"Run Id","description":"Run whose decisions are read."},"head_only":{"type":"boolean","title":"Head Only","description":"If True, drop rows whose id appears as another row's ``supersedes_step_id`` (i.e. only return chain heads). When two decisions concurrently supersede the same prior decision (a diamond), both new steps are returned as heads.","default":false}},"additionalProperties":false,"type":"object","required":["run_id"],"title":"AgentReadDecisionsInput","description":"Input for ``agent.read_decisions``."},"AgentReadDecisionsOutput":{"properties":{"run_id":{"type":"string","format":"uuid","title":"Run Id"},"decisions":{"items":{"$ref":"#/components/schemas/DecisionRecord"},"type":"array","title":"Decisions"}},"type":"object","required":["run_id","decisions"],"title":"AgentReadDecisionsOutput","description":"Result projection for ``agent.read_decisions``."},"AgentRecordDecisionInput":{"properties":{"run_id":{"type":"string","format":"uuid","title":"Run Id","description":"Run this decision belongs to. The caller (agent) supplies this explicitly; the capability does not infer it from context."},"reasoning":{"type":"string","maxLength":8192,"minLength":1,"title":"Reasoning","description":"Why this decision was made (free text)."},"chosen":{"type":"string","maxLength":512,"minLength":1,"title":"Chosen","description":"What was chosen."},"alternatives":{"items":{"type":"string"},"type":"array","title":"Alternatives","description":"Alternatives considered (may be empty)."},"related_node_ids":{"items":{"type":"string"},"type":"array","title":"Related Node Ids","description":"Optional Neo4j node IDs the decision affects. Advisory; not FK-validated."},"supersedes_step_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Supersedes Step Id","description":"If this decision revises a prior one, the FK to that prior DECISION step. Must live in the same run."}},"additionalProperties":false,"type":"object","required":["run_id","reasoning","chosen"],"title":"AgentRecordDecisionInput","description":"Input for ``agent.record_decision``."},"AgentRecordDecisionOutput":{"properties":{"step_id":{"type":"string","format":"uuid","title":"Step Id","description":"UUID of the new DECISION step."},"run_id":{"type":"string","format":"uuid","title":"Run Id","description":"Run the step belongs to."},"seq":{"type":"integer","title":"Seq","description":"Monotonic step sequence within the run."},"supersedes_step_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Supersedes Step Id","description":"The prior step this one supersedes, if any."},"chain_depth":{"type":"integer","title":"Chain Depth","description":"1 for a root decision; n+1 for the n-th revision in a chain."},"recorded_at":{"type":"string","title":"Recorded At","description":"ISO-8601 timestamp (UTC)."}},"type":"object","required":["step_id","run_id","seq","chain_depth","recorded_at"],"title":"AgentRecordDecisionOutput","description":"Result projection for a newly-recorded decision step."},"AgentRecordFindingInput":{"properties":{"target_node_id":{"type":"string","format":"uuid","title":"Target Node Id","description":"UUID of the ``code.*`` node this finding targets. Non-code targets raise a FindingTargetError."},"kind":{"type":"string","maxLength":64,"minLength":1,"title":"Kind","description":"Finding category (``bug``, ``dead_code``, ``complexity``, ...). Required, non-empty."},"severity":{"type":"string","enum":["critical","high","medium","low","info"],"title":"Severity","description":"Severity tier for triage."},"description":{"type":"string","maxLength":4096,"minLength":1,"title":"Description","description":"Human-readable description. Required, non-empty. Truncated for the node's display name; full text lives in ``properties['description']``."},"source":{"type":"string","enum":["agent","rule"],"title":"Source","description":"Provenance tag. ``agent`` for direct LLM submissions; ``rule`` reserved for the OXA-487 rule-evaluation worker.","default":"agent"},"evidence":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Evidence","description":"Optional structured evidence (line numbers, snippets, diff fragments). Carried verbatim into ``properties['evidence']``."}},"additionalProperties":false,"type":"object","required":["target_node_id","kind","severity","description"],"title":"AgentRecordFindingInput","description":"Input for ``agent.record_finding``."},"AgentRecordFindingOutput":{"properties":{"finding_id":{"type":"string","format":"uuid","title":"Finding Id","description":"UUID of the new ``agent.finding`` node."},"target_node_id":{"type":"string","format":"uuid","title":"Target Node Id","description":"UUID of the target ``code.*`` node."},"kind":{"type":"string","title":"Kind","description":"Finding category."},"severity":{"type":"string","title":"Severity","description":"Severity tier."},"source":{"type":"string","title":"Source","description":"Provenance tag."},"recorded_at":{"type":"string","title":"Recorded At","description":"ISO-8601 timestamp of recording (UTC)."}},"type":"object","required":["finding_id","target_node_id","kind","severity","source","recorded_at"],"title":"AgentRecordFindingOutput","description":"Projection of a newly-recorded finding node."},"AgentReleaseClaimInput":{"properties":{"claim_id":{"type":"string","format":"uuid","title":"Claim Id","description":"UUID of the ``agent.claim`` node to release. The JWT caller must be the user that opened the claim."},"platform_claim_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Platform Claim Id","description":"UUID of the ``run.work_claim`` Postgres row, when the claim was acquired in a platform run context. If provided, the Postgres row is released independently from the Neo4j claim node. Returned by ``agent.claim_work`` as ``platform_claim_id``."}},"additionalProperties":false,"type":"object","required":["claim_id"],"title":"AgentReleaseClaimInput","description":"Input for ``agent.release_claim``."},"AgentReleaseClaimOutput":{"properties":{"claim_id":{"type":"string","format":"uuid","title":"Claim Id","description":"UUID of the claim that was (or was already) released."},"status":{"type":"string","title":"Status","description":"Final status — ``'released'`` after a real release; ``'abandoned'`` or the previous terminal status when idempotent."},"already_released":{"type":"boolean","title":"Already Released","description":"``True`` when the claim was already in a terminal state before this call."}},"type":"object","required":["claim_id","status","already_released"],"title":"AgentReleaseClaimOutput","description":"Result of releasing a claim."},"AgentResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"system_prompt_md":{"type":"string","title":"System Prompt Md"},"allowed_capability_globs":{"items":{"type":"string"},"type":"array","title":"Allowed Capability Globs"},"denied_capability_globs":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Denied Capability Globs"},"default_tier":{"type":"string","title":"Default Tier"},"default_model_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Model Id"},"step_budget":{"type":"integer","title":"Step Budget"},"credit_budget":{"type":"integer","title":"Credit Budget"},"is_builtin":{"type":"boolean","title":"Is Builtin"}},"type":"object","required":["id","workspace_id","slug","name","description","system_prompt_md","allowed_capability_globs","denied_capability_globs","default_tier","default_model_id","step_budget","credit_budget","is_builtin"],"title":"AgentResponse","description":"Public projection of an AgentDefinition row."},"AgentStartSessionInput":{"properties":{"task_description":{"type":"string","maxLength":2048,"minLength":1,"title":"Task Description","description":"Free-form description of what the agent is about to do. Required, non-empty. The first 64 characters become the session node's display name; the full text lives in ``properties['task_description']``."},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata","description":"Optional free-form metadata blob merged into the session node's properties. Keys must not collide with reserved fields (user_id, status, started_at, etc.) — collisions are logged and silently dropped."}},"additionalProperties":false,"type":"object","required":["task_description"],"title":"AgentStartSessionInput","description":"Input for ``agent.start_session``."},"AgentStartSessionOutput":{"properties":{"session_id":{"type":"string","format":"uuid","title":"Session Id","description":"UUID of the new ``agent.session`` node."},"task_description":{"type":"string","title":"Task Description","description":"Full task description stored on the node."},"status":{"type":"string","title":"Status","description":"Session status — always ``'active'`` at creation."},"started_at":{"type":"string","title":"Started At","description":"ISO-8601 timestamp of session creation (UTC)."}},"type":"object","required":["session_id","task_description","status","started_at"],"title":"AgentStartSessionOutput","description":"Projection of a freshly-opened agent session node."},"AgentTriggerSubscriberRow":{"properties":{"kind":{"type":"string","title":"Kind","default":"agent_trigger"},"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"enabled":{"type":"boolean","title":"Enabled"},"agent_kind":{"type":"string","title":"Agent Kind"},"model_tier":{"type":"string","title":"Model Tier"},"execution_mode":{"type":"string","title":"Execution Mode"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","enabled","agent_kind","model_tier","execution_mode","created_at"],"title":"AgentTriggerSubscriberRow","description":"Agent trigger subscribed to a slug."},"AgentUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"system_prompt_md":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"System Prompt Md"},"allowed_capability_globs":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allowed Capability Globs"},"denied_capability_globs":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Denied Capability Globs"},"default_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Tier","description":"Model tier override. One of ``'level_1'``, ``'level_2'``, ``'level_3'``. Pass ``null`` to reset to ``'level_1'``."},"default_model_id":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Default Model Id","description":"Explicit model override. Pass an empty string ``''`` to clear the override and fall back to ``default_tier``."},"step_budget":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Step Budget"},"credit_budget":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credit Budget"}},"type":"object","title":"AgentUpdate","description":"Body for PATCH /agents/{id} — all fields optional."},"AnalyticsResponse":{"properties":{"range":{"type":"string","title":"Range"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"total":{"type":"integer","title":"Total"},"success_rate":{"type":"number","title":"Success Rate"},"volume":{"items":{"$ref":"#/components/schemas/VolumeBucket"},"type":"array","title":"Volume"},"top_slugs":{"items":{"$ref":"#/components/schemas/CountByKey"},"type":"array","title":"Top Slugs"},"top_kinds":{"items":{"$ref":"#/components/schemas/CountByKey"},"type":"array","title":"Top Kinds"},"latency":{"$ref":"#/components/schemas/LatencyPercentiles"},"analytics_available":{"type":"boolean","title":"Analytics Available"}},"type":"object","required":["range","workspace_id","total","success_rate","volume","top_slugs","top_kinds","latency","analytics_available"],"title":"AnalyticsResponse","description":"Bundle returned by ``GET /v1/events/analytics``."},"AnswerResponse":{"properties":{"narrative":{"type":"string","title":"Narrative","description":"Human-readable answer composed by the agent."},"citations":{"items":{"$ref":"#/components/schemas/NodeCitationResponse"},"type":"array","title":"Citations","description":"Nodes the agent cited as evidence."},"candidate_count":{"type":"integer","title":"Candidate Count","description":"Total number of candidate nodes retrieved before ranking and answering."},"retrieval_mode":{"type":"string","title":"Retrieval Mode","description":"Retrieval strategy used by the agent — 'vector', 'structural', or 'hybrid'."}},"type":"object","required":["narrative","citations","candidate_count","retrieval_mode"],"title":"AnswerResponse","description":"Projection of a Question Answerer result."},"ApiKeyCreateRequest":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name","description":"User-provided label shown in the Settings UI."},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id","description":"Workspace the key is pinned to. Must be visible to the caller."},"audience":{"type":"string","enum":["api","mcp"],"title":"Audience","description":"Token audience — 'api' (default) for the public developer API, 'mcp' for MCP-server access. Unknown values are rejected at validation with HTTP 422.","default":"api"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At","description":"Optional hard expiry (UTC). Null = no expiry."},"scopes":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Scopes","description":"Optional list of scope strings (advisory today). Examples: ``ontology:read``, ``ontology:write``, ``mcp``."}},"type":"object","required":["name","workspace_id"],"title":"ApiKeyCreateRequest","description":"Body for POST /v1/auth/me/api-keys."},"ApiKeyCreateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"token_prefix":{"type":"string","title":"Token Prefix"},"plaintext":{"type":"string","title":"Plaintext"},"audience":{"type":"string","title":"Audience"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"scopes":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Scopes"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","workspace_id","token_prefix","plaintext","audience","expires_at","scopes","created_at"],"title":"ApiKeyCreateResponse","description":"Response for POST /v1/auth/me/api-keys.\n\nThe ``plaintext`` field is the full bearer token — shown exactly\nonce at creation. The client must copy it immediately; subsequent\nGETs return only the prefix."},"ApiKeyRow":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"token_prefix":{"type":"string","title":"Token Prefix"},"audience":{"type":"string","title":"Audience"},"scopes":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Scopes"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"last_used_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Used Ip"},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Revoked At"},"request_count":{"type":"integer","title":"Request Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","workspace_id","token_prefix","audience","scopes","expires_at","last_used_at","last_used_ip","revoked_at","request_count","created_at"],"title":"ApiKeyRow","description":"Slim projection used by list + revoke responses."},"ApiKeyUsageSummary":{"properties":{"api_key_id":{"type":"string","format":"uuid","title":"Api Key Id"},"window_days":{"type":"integer","title":"Window Days"},"request_count":{"type":"integer","title":"Request Count"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"daily":{"items":{"$ref":"#/components/schemas/DailyUsagePoint"},"type":"array","title":"Daily"}},"type":"object","required":["api_key_id","window_days","request_count","last_used_at","daily"],"title":"ApiKeyUsageSummary","description":"Aggregate usage for GET /v1/auth/me/api-keys/{id}/usage."},"ApprovalDecision":{"type":"string","enum":["pending","approved","rejected","expired"],"title":"ApprovalDecision"},"BaseEventKind":{"properties":{"kind":{"type":"string","title":"Kind"},"label":{"type":"string","title":"Label"},"category":{"type":"string","title":"Category"},"description":{"type":"string","title":"Description"},"supports_changed_fields":{"type":"boolean","title":"Supports Changed Fields"}},"type":"object","required":["kind","label","category","description","supports_changed_fields"],"title":"BaseEventKind","description":"One entry in ``GET /v1/events/kinds``.\n\nDrives the kind picker in the create / edit modal: each row\nsurfaces the canonical ``kind`` string, a short human label,\na category for grouping (``node`` / ``edge`` / ``source`` /\n``type``) and whether the kind supports ``changed_fields_any``\nfiltering (true for ``*.updated`` kinds only)."},"BenchmarkRow":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"metric_definition_id":{"type":"string","format":"uuid","title":"Metric Definition Id"},"metric_name":{"type":"string","title":"Metric Name"},"value":{"type":"number","title":"Value"},"sample_count":{"type":"integer","title":"Sample Count"},"window_key":{"type":"string","title":"Window Key"},"window_start":{"type":"string","format":"date-time","title":"Window Start"},"window_end":{"type":"string","format":"date-time","title":"Window End"},"baseline_value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Baseline Value"},"delta_vs_baseline":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delta Vs Baseline"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","metric_definition_id","metric_name","value","sample_count","window_key","window_start","window_end","created_at"],"title":"BenchmarkRow","description":"One benchmark rollup row.\n\nAttributes:\n    id: Primary key of the AgentBenchmark row.\n    metric_definition_id: FK to the metric definition.\n    metric_name: Denormalized metric name.\n    value: Computed metric value for this window.\n    sample_count: Number of events aggregated.\n    window_key: Aggregation window label (``24h``, ``7d``, ``30d``).\n    window_start: Inclusive start of the aggregation window (UTC).\n    window_end: Inclusive end of the aggregation window (UTC).\n    baseline_value: Value from the prior window or ``None``.\n    delta_vs_baseline: ``value - baseline_value`` or ``None``.\n    created_at: When this benchmark row was inserted."},"BenchmarksResponse":{"properties":{"benchmarks":{"items":{"$ref":"#/components/schemas/BenchmarkRow"},"type":"array","title":"Benchmarks"},"window":{"type":"string","title":"Window"},"metric":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Metric"}},"type":"object","required":["benchmarks","window"],"title":"BenchmarksResponse","description":"Response envelope for ``GET /benchmarks``.\n\nAttributes:\n    benchmarks: List of benchmark rows matching the query.\n    window: The requested window key (24h, 7d, or 30d).\n    metric: The requested metric name filter, or None."},"BillingCreditsBalanceInput":{"properties":{},"additionalProperties":false,"type":"object","title":"BillingCreditsBalanceInput","description":"Input — empty.\n\nThe tenant the balance belongs to is inferred from the caller's\ncontext (``CallContext.tenant_id``). Accepting no arguments keeps\nthe capability impossible to misuse from a prompt-injected agent."},"BillingCreditsBalanceOutput":{"properties":{"tenant_id":{"type":"string","format":"uuid","title":"Tenant Id","description":"Tenant whose balance is reported."},"balance":{"type":"integer","title":"Balance","description":"Current credits — ``SUM(delta)`` across non-deleted rows in ``billing.credit_ledger`` for the tenant."}},"type":"object","required":["tenant_id","balance"],"title":"BillingCreditsBalanceOutput","description":"Current balance for the caller's tenant."},"CatalogModel":{"properties":{"id":{"type":"string","title":"Id"},"provider":{"type":"string","title":"Provider"},"display_name":{"type":"string","title":"Display Name"},"tier":{"type":"string","title":"Tier"},"tier_brand":{"type":"string","title":"Tier Brand"},"capabilities":{"items":{"type":"string"},"type":"array","title":"Capabilities"},"context_window":{"type":"integer","title":"Context Window"},"pro_required":{"type":"boolean","title":"Pro Required"},"is_oxagen_managed":{"type":"boolean","title":"Is Oxagen Managed"},"byok_required":{"type":"boolean","title":"Byok Required"}},"type":"object","required":["id","provider","display_name","tier","tier_brand","capabilities","context_window","pro_required","is_oxagen_managed","byok_required"],"title":"CatalogModel","description":"A single model entry in the catalog response.\n\nAttributes:\n    id: Provider model ID (e.g. ``\"claude-haiku-4-5-20251001\"``).\n    provider: Provider slug (e.g. ``\"anthropic\"``).\n    display_name: Human-readable model name for UI display.\n    tier: Internal tier string (``\"level_1\"`` / ``\"level_2\"`` /\n        ``\"level_3\"``).\n    tier_brand: User-visible tier name (``\"Oxagen\"`` / ``\"Oxagen+\"``\n        / ``\"Oxagen+ Pro\"``).\n    capabilities: List of capability strings (``\"chat\"``,\n        ``\"tools\"``, ``\"streaming\"``, ``\"vision\"``).\n    context_window: Maximum context window in tokens.\n    pro_required: True when Oxagen-managed access requires Pro.\n    is_oxagen_managed: True when this model is the Oxagen-managed\n        default for its tier.\n    byok_required: True when the workspace has no credential for\n        this model's provider (must add a key before using it)."},"CatalogResponse":{"properties":{"models":{"items":{"$ref":"#/components/schemas/CatalogModel"},"type":"array","title":"Models"},"workspace_plan":{"type":"string","title":"Workspace Plan"}},"type":"object","required":["models","workspace_plan"],"title":"CatalogResponse","description":"Response for GET /workspace-models/catalog.\n\nAttributes:\n    models: All non-deprecated catalog models with workspace context\n        applied (byok_required, eligibility).\n    workspace_plan: Current plan slug for the requesting workspace's\n        tenant (``\"free\"`` / ``\"pro\"`` / etc.)."},"CitationProjection":{"properties":{"node_id":{"type":"string","format":"uuid","title":"Node Id","description":"UUID of the cited workspace node."},"type":{"type":"string","title":"Type","description":"Node type tag."},"name":{"type":"string","title":"Name","description":"Node display name."},"excerpt":{"type":"string","title":"Excerpt","description":"Short LLM-produced snippet explaining the citation.","default":""}},"type":"object","required":["node_id","type","name"],"title":"CitationProjection","description":"One node cited in the answer narrative."},"ClaimItem":{"properties":{"claim_id":{"type":"string","format":"uuid","title":"Claim Id","description":"UUID of the ``agent.claim`` node."},"session_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Session Id","description":"UUID of the owning session."},"target_node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Target Node Id","description":"UUID of the claimed target node."},"intent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Intent","description":"Intent text stored on the claim."},"claimed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claimed At","description":"ISO-8601 timestamp of claim creation (UTC)."}},"type":"object","required":["claim_id"],"title":"ClaimItem","description":"Single active claim in the output list."},"CommitTouchResponse":{"properties":{"commit":{"$ref":"#/components/schemas/NodeResponse"},"action":{"type":"string","title":"Action","description":"``added`` / ``modified`` / ``removed`` / ``renamed`` / ``copied`` from the touched edge."},"author":{"anyOf":[{"$ref":"#/components/schemas/NodeResponse"},{"type":"null"}]},"diff_excerpt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Diff Excerpt","description":"First 1000 chars of diff_patch."}},"type":"object","required":["commit","action"],"title":"CommitTouchResponse","description":"Public projection of a :class:`CommitTouch` row."},"CountByKey":{"properties":{"key":{"type":"string","title":"Key"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["key","count"],"title":"CountByKey","description":"A name → count tuple for breakdown tables."},"CreateCredentialRequest":{"properties":{"provider":{"$ref":"#/components/schemas/ModelProvider","description":"Provider — currently 'anthropic' or 'openai'."},"label":{"type":"string","maxLength":64,"minLength":1,"title":"Label","description":"Short owner-facing label (unique per provider in this workspace). Examples: 'primary', 'team-account'."},"api_key":{"type":"string","maxLength":512,"minLength":8,"title":"Api Key","description":"Raw provider API key. Never echoed back."}},"additionalProperties":false,"type":"object","required":["provider","label","api_key"],"title":"CreateCredentialRequest","description":"Body for POST /credentials."},"CreateSlugRequest":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"trigger_kind":{"type":"string","maxLength":80,"title":"Trigger Kind","default":""},"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Description"},"filter_json":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Filter Json"}},"type":"object","required":["name"],"title":"CreateSlugRequest","description":"Body for ``POST /v1/events/slugs``.\n\n``trigger_kind`` may be the empty string when the caller wants\nto match multiple base kinds. In that case the authoritative\nlist lives in ``filter_json[\"kinds\"]`` and the dispatcher's\nkind pre-filter short-circuits on empty."},"CreateWebhookRequest":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"url":{"type":"string","maxLength":2048,"minLength":1,"title":"Url"},"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Description"},"event_filter":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Event Filter","description":"Filter DSL — see ``oxagen.webhooks.filter_dsl``. Empty / omitted means subscribe to every event in the workspace."}},"type":"object","required":["name","url"],"title":"CreateWebhookRequest","description":"Body for ``POST /v1/webhooks``."},"CredentialListResponse":{"properties":{"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"credentials":{"items":{"$ref":"#/components/schemas/CredentialResponse"},"type":"array","title":"Credentials"}},"type":"object","required":["workspace_id","credentials"],"title":"CredentialListResponse","description":"List response wrapper."},"CredentialResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"provider":{"type":"string","title":"Provider"},"label":{"type":"string","title":"Label"},"key_preview":{"type":"string","title":"Key Preview"},"last_health_check_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Health Check At"},"health_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Health Status"},"health_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Health Error"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","workspace_id","provider","label","key_preview","last_health_check_at","health_status","health_error","created_at","updated_at"],"title":"CredentialResponse","description":"Public-safe view of a stored credential — never includes the secret."},"CreditReceiptResponse":{"properties":{"ledger_id":{"type":"string","format":"uuid","title":"Ledger Id","description":"billing.credit_ledger.id for the reservation."},"kind":{"type":"string","title":"Kind","description":"Metered operation kind (e.g. 'ontology.search.hybrid')."},"amount":{"type":"integer","title":"Amount","description":"Credits charged (positive integer)."}},"type":"object","required":["ledger_id","kind","amount"],"title":"CreditReceiptResponse","description":"API shape for a credit reservation receipt."},"DailyUsagePoint":{"properties":{"day":{"type":"string","format":"date-time","title":"Day"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["day","count"],"title":"DailyUsagePoint","description":"One day in the rolling usage window."},"DecisionRecord":{"properties":{"step_id":{"type":"string","format":"uuid","title":"Step Id"},"run_id":{"type":"string","format":"uuid","title":"Run Id"},"seq":{"type":"integer","title":"Seq"},"recorded_at":{"type":"string","title":"Recorded At"},"supersedes_step_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Supersedes Step Id"},"reasoning":{"type":"string","title":"Reasoning"},"chosen":{"type":"string","title":"Chosen"},"alternatives":{"items":{"type":"string"},"type":"array","title":"Alternatives"},"related_node_ids":{"items":{"type":"string"},"type":"array","title":"Related Node Ids"}},"type":"object","required":["step_id","run_id","seq","recorded_at","supersedes_step_id","reasoning","chosen","alternatives","related_node_ids"],"title":"DecisionRecord","description":"One decision row in the output projection."},"DeleteNodesByTypeResponse":{"properties":{"deleted_nodes":{"type":"integer","title":"Deleted Nodes","description":"Number of nodes soft-deleted."},"deleted_edges":{"type":"integer","title":"Deleted Edges","description":"Number of incident edges soft-deleted."}},"type":"object","required":["deleted_nodes","deleted_edges"],"title":"DeleteNodesByTypeResponse","description":"Response for DELETE /ontology/nodes."},"DispatchRunRequest":{"properties":{"agent_id":{"type":"string","format":"uuid","title":"Agent Id"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"title":{"type":"string","maxLength":255,"minLength":1,"title":"Title","description":"Human-readable title for this execution."},"goal":{"type":"string","maxLength":4096,"minLength":1,"title":"Goal","description":"Free-text goal for the agent."},"playbook_version_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Playbook Version Id","description":"Playbook version to execute. None = agent default behaviour (P-2a)."},"budget_usd":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Budget Usd","description":"Per-execution spend cap in USD (e.g. 1.50)."},"timeout_seconds":{"anyOf":[{"type":"integer","maximum":86400.0,"minimum":1.0},{"type":"null"}],"title":"Timeout Seconds","description":"Wall-clock deadline in seconds (1–86400)."},"idempotency_key":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Idempotency Key","description":"Caller-supplied deduplication key."}},"additionalProperties":false,"type":"object","required":["agent_id","workspace_id","title","goal"],"title":"DispatchRunRequest","description":"Body for ``POST /v1/runs``.\n\nAttributes:\n    agent_id: UUID of the ``agent.agents`` row to run.\n    workspace_id: UUID of the target workspace. Must match the\n        caller's RLS context.\n    title: Human-readable title for this execution.\n    goal: Free-text goal statement passed to the agent.\n    playbook_version_id: Optional playbook version to execute.\n        When ``None`` the agent's default behaviour is used.\n    budget_usd: Optional per-execution spend cap in USD.\n    timeout_seconds: Optional wall-clock deadline in seconds.\n    idempotency_key: Optional caller-supplied key for deduplication.\n        Resubmitting with the same key returns the prior execution."},"DispatchRunResponse":{"properties":{"execution_id":{"type":"string","format":"uuid","title":"Execution Id"},"task_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Task Ids"},"was_duplicate":{"type":"boolean","title":"Was Duplicate"}},"type":"object","required":["execution_id","task_ids","was_duplicate"],"title":"DispatchRunResponse","description":"Response for ``POST /v1/runs``.\n\nAttributes:\n    execution_id: The created or existing Execution UUID.\n    task_ids: UUIDs of the Task rows enqueued.\n    was_duplicate: True when the response reuses a prior execution\n        that matched the idempotency key."},"DryRunRequest":{"properties":{"trigger_kind":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Trigger Kind"},"filter_json":{"additionalProperties":true,"type":"object","title":"Filter Json"},"sample_limit":{"type":"integer","maximum":50.0,"minimum":1.0,"title":"Sample Limit","default":10}},"type":"object","title":"DryRunRequest","description":"Body for ``POST /v1/events/slugs/dry-run``."},"DryRunResponse":{"properties":{"scanned":{"type":"integer","title":"Scanned"},"matched":{"type":"integer","title":"Matched"},"samples":{"items":{"$ref":"#/components/schemas/DryRunSample"},"type":"array","title":"Samples"}},"type":"object","required":["scanned","matched","samples"],"title":"DryRunResponse","description":"Match count + samples for a candidate filter."},"DryRunSample":{"properties":{"entry_id":{"type":"string","title":"Entry Id"},"kind":{"type":"string","title":"Kind"},"payload":{"additionalProperties":true,"type":"object","title":"Payload"}},"type":"object","required":["entry_id","kind","payload"],"title":"DryRunSample","description":"One sampled event that matched the candidate filter."},"EdgeCreateRequest":{"properties":{"source_node_id":{"type":"string","format":"uuid","title":"Source Node Id","description":"UUID of the originating node."},"target_node_id":{"type":"string","format":"uuid","title":"Target Node Id","description":"UUID of the destination node."},"type":{"type":"string","maxLength":80,"pattern":"^[a-z][a-z0-9_.]*$","title":"Type","description":"Edge type identifier. Lowercase, optionally dot-namespaced (e.g. 'attended_by', 'code.calls') — must match [a-z][a-z0-9_.]*."},"properties":{"additionalProperties":true,"type":"object","title":"Properties","description":"Free-form JSONB properties attached to the edge."},"weight":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Weight","description":"Optional relationship weight in [0.0, 1.0]."}},"type":"object","required":["source_node_id","target_node_id","type"],"title":"EdgeCreateRequest","description":"Body for POST /ontology/edges."},"EdgeResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"Edge UUID primary key."},"type":{"type":"string","title":"Type","description":"Edge type identifier."},"source_node_id":{"type":"string","format":"uuid","title":"Source Node Id","description":"Originating node UUID."},"target_node_id":{"type":"string","format":"uuid","title":"Target Node Id","description":"Destination node UUID."},"properties":{"additionalProperties":true,"type":"object","title":"Properties","description":"Free-form JSONB properties."},"weight":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Weight","description":"Optional relationship weight."},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id","description":"Workspace UUID owning this edge."},"created_at":{"type":"string","title":"Created At","description":"ISO-8601 timestamp of creation (UTC)."}},"type":"object","required":["id","type","source_node_id","target_node_id","properties","weight","workspace_id","created_at"],"title":"EdgeResponse","description":"Public projection of an Edge row."},"EligibilityResponse":{"properties":{"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"byok_enabled":{"type":"boolean","title":"Byok Enabled"},"plan":{"type":"string","title":"Plan"},"upgrade_required_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upgrade Required To","description":"When ``byok_enabled`` is false, the lowest plan that would enable BYOK. Surfaced in the UI as an upgrade CTA."}},"type":"object","required":["workspace_id","byok_enabled","plan"],"title":"EligibilityResponse","description":"Response for GET /eligibility."},"ExpenseLine":{"properties":{"transaction_id":{"type":"string","format":"uuid","title":"Transaction Id"},"description":{"type":"string","maxLength":200,"minLength":1,"title":"Description"},"amount":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Amount"},"currency":{"type":"string","title":"Currency","default":"USD"},"category":{"type":"string","title":"Category","default":"uncategorized"},"transaction_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Transaction Date"},"has_receipt":{"type":"boolean","title":"Has Receipt","default":false},"receipt_document_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Receipt Document Id"}},"additionalProperties":false,"type":"object","required":["transaction_id","description","amount"],"title":"ExpenseLine","description":"A single line on the assembled expense report.\n\nAttributes:\n    transaction_id: UUID of the source ``financial.transaction``\n        node.\n    description: Short human-readable label — falls back to the\n        transaction ``name`` when no ``financial.line_item`` is\n        linked via ``[:CONTAINS]``.\n    amount: Positive decimal in the report's currency.\n    currency: ISO-4217 code; populated from the transaction node.\n    category: ``subcategory_l1`` from the transaction node, used\n        for grouping and per-category subtotals.\n    transaction_date: ISO-8601 date the spend was incurred.\n    has_receipt: ``True`` when at least one ``[:HAS_RECEIPT]``\n        edge points at a ``financial.invoice_document`` node.\n    receipt_document_id: UUID of the linked invoice document\n        when present."},"ExpenseReport":{"properties":{"trip_id":{"type":"string","format":"uuid","title":"Trip Id"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"total":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Total","default":"0"},"currency":{"type":"string","title":"Currency","default":"USD"},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date"},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End Date"},"lines":{"items":{"$ref":"#/components/schemas/ExpenseLine"},"type":"array","title":"Lines"},"category_totals":{"additionalProperties":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},"type":"object","title":"Category Totals"},"coverage":{"$ref":"#/components/schemas/ReceiptCoverage"},"generated_at":{"type":"string","format":"date-time","title":"Generated At"}},"additionalProperties":false,"type":"object","required":["trip_id","workspace_id"],"title":"ExpenseReport","description":"Full expense report for a closed trip.\n\nAttributes:\n    trip_id: UUID of the source ``financial.trip`` node, or the\n        id the caller passed when the trip node is absent\n        (graceful degradation against OXA-724 not-yet-merged).\n    workspace_id: Workspace scope — included so MCP tooling can\n        re-fetch without needing extra context.\n    total: Sum of every ``ExpenseLine.amount``.\n    currency: ISO-4217 code; the first non-empty currency on any\n        transaction wins. Mixed-currency trips surface as the\n        first one encountered — categorisation of multi-currency\n        trips is OXA-735's problem, not this one.\n    start_date: Earliest ``transaction_date`` across the lines.\n    end_date: Latest ``transaction_date`` across the lines.\n    lines: Per-transaction ``ExpenseLine`` rows, ordered by\n        ``transaction_date`` ascending then ``transaction_id``.\n    category_totals: ``{category: subtotal}`` rolled up from\n        ``lines``. Empty when ``lines`` is empty.\n    coverage: ``ReceiptCoverage`` summary.\n    generated_at: UTC timestamp of report assembly."},"ExtractedEdgeResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"Newly-created edge UUID."},"type":{"type":"string","title":"Type","description":"Edge type the refiner assigned."},"source_node_id":{"type":"string","format":"uuid","title":"Source Node Id","description":"UUID of the originating persisted node."},"target_node_id":{"type":"string","format":"uuid","title":"Target Node Id","description":"UUID of the destination persisted node."},"source_ref":{"type":"string","title":"Source Ref","description":"Refiner-local ref for the source node."},"target_ref":{"type":"string","title":"Target Ref","description":"Refiner-local ref for the target node."},"properties":{"additionalProperties":true,"type":"object","title":"Properties","description":"JSONB properties extracted on the edge."}},"type":"object","required":["id","type","source_node_id","target_node_id","source_ref","target_ref","properties"],"title":"ExtractedEdgeResponse","description":"Projection of a freshly-persisted refiner edge."},"ExtractedNodeResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"Newly-created node UUID."},"ref":{"type":"string","title":"Ref","description":"Refiner-local reference string (e.g. 'n1') used to wire this node into extracted edges."},"type":{"type":"string","title":"Type","description":"Node type the refiner assigned."},"name":{"type":"string","title":"Name","description":"Human-readable node name."},"properties":{"additionalProperties":true,"type":"object","title":"Properties","description":"JSONB properties extracted by the refiner."}},"type":"object","required":["id","ref","type","name","properties"],"title":"ExtractedNodeResponse","description":"Projection of a freshly-persisted refiner node."},"FindingItem":{"properties":{"finding_id":{"type":"string","format":"uuid","title":"Finding Id","description":"UUID of the finding node."},"target_node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Target Node Id","description":"UUID of the target ``code.*`` node."},"kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind","description":"Finding category."},"severity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Severity","description":"Severity tier."},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source","description":"Provenance tag."},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Human-readable description."},"recorded_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recorded At","description":"ISO-8601 timestamp of recording (UTC)."},"evidence":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Evidence","description":"Structured evidence blob."}},"type":"object","required":["finding_id"],"title":"FindingItem","description":"Single finding in the output list."},"GraphNeighborhoodResponse":{"properties":{"center":{"anyOf":[{"$ref":"#/components/schemas/NodeResponse"},{"type":"null"}]},"nodes":{"items":{"$ref":"#/components/schemas/NodeResponse"},"type":"array","title":"Nodes"},"edges":{"items":{"$ref":"#/components/schemas/EdgeResponse"},"type":"array","title":"Edges"},"candidates":{"items":{"$ref":"#/components/schemas/NodeResponse"},"type":"array","title":"Candidates"}},"type":"object","title":"GraphNeighborhoodResponse","description":"API projection of an Explore-tab neighborhood query.\n\nWraps a :class:`NeighborhoodRecord` plus the candidate list from\na free-text search so the UI can either render the resolved\nneighborhood directly (single match → top-1 used as center) OR\nshow a picker when the query was ambiguous.\n\nAttributes:\n    center: The resolved center node, or ``None`` when neither\n        ``q`` matched anything nor ``node_id`` was provided.\n    nodes: Every node in the bidirectional N-hop expansion,\n        including ``center`` first when present.\n    edges: Every live edge whose endpoints both live in\n        ``nodes``.\n    candidates: Up to 10 search candidates when ``q`` was\n        provided. Empty when ``node_id`` was used directly."},"GraphOverviewRecord":{"properties":{"supernodes":{"items":{"$ref":"#/components/schemas/GraphOverviewSupernode"},"type":"array","title":"Supernodes"},"superedges":{"items":{"$ref":"#/components/schemas/GraphOverviewSuperedge"},"type":"array","title":"Superedges"},"total_node_count":{"type":"integer","title":"Total Node Count","default":0},"total_edge_count":{"type":"integer","title":"Total Edge Count","default":0},"truncated":{"type":"boolean","title":"Truncated","default":false}},"type":"object","title":"GraphOverviewRecord","description":"Bounded aggregation of a workspace graph for the Explore tab.\n\nReturned by :meth:`OntologyRepository.graph_overview`. The size of\nthe payload is bounded by ``max_supernodes`` regardless of how\nmany underlying nodes / edges the workspace holds — this is the\ncontract that lets Explore work on workspaces with 100k+ nodes\nwithout overwhelming the renderer or the wire.\n\nAttributes:\n    supernodes: The bounded aggregate clusters. Order: descending\n        by ``members_count`` so the largest clusters are first.\n    superedges: Inter-supernode edge bundles whose endpoints both\n        land in ``supernodes``. Edges to clusters that didn't make\n        the ``max_supernodes`` cut are dropped.\n    total_node_count: Total live nodes in the workspace, before\n        aggregation. Lets the UI render \"showing N clusters of M\n        nodes\" without a second query.\n    total_edge_count: Total live edges in the workspace.\n    truncated: ``True`` when the workspace had more clusters than\n        ``max_supernodes`` and the cut-off dropped some. The UI\n        should surface a \"raise the cluster cap\" affordance when\n        set."},"GraphOverviewSuperedge":{"properties":{"source_id":{"type":"string","title":"Source Id"},"target_id":{"type":"string","title":"Target Id"},"type":{"type":"string","title":"Type"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["source_id","target_id","type","count"],"title":"GraphOverviewSuperedge","description":"One aggregate edge bundle between two supernodes.\n\nCollapses every underlying edge between members of ``source_id``\nand members of ``target_id`` into a single visual line. The\nbundle's type is the most-common underlying edge type; the count\nis the bundle cardinality so the renderer can size the line.\n\nAttributes:\n    source_id: Supernode id at the bundle's source end.\n    target_id: Supernode id at the bundle's target end.\n    type: Dominant edge type in the bundle (highest-count rel\n        type among the underlying edges). Surface a single\n        label rather than draw a parallel-edge cluster.\n    count: Total number of underlying live edges the bundle\n        represents."},"GraphOverviewSupernode":{"properties":{"id":{"type":"string","title":"Id"},"type":{"type":"string","title":"Type"},"group_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Group Key"},"members_count":{"type":"integer","title":"Members Count"},"top_member_names":{"items":{"type":"string"},"type":"array","title":"Top Member Names"},"aggregate_importance":{"type":"number","title":"Aggregate Importance","default":0.0},"x":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"X"},"y":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Y"}},"type":"object","required":["id","type","members_count"],"title":"GraphOverviewSupernode","description":"One aggregate cluster in :class:`GraphOverviewRecord`.\n\nA supernode represents many underlying nodes grouped by an\nexplicit dimension tuple — typically ``(type, path_prefix)`` for\ncode-graph workspaces. The renderer draws supernodes as a single\nvisual entity and reveals the underlying members on click via the\npaginated :meth:`OntologyRepository.list_nodes` route.\n\nAttributes:\n    id: Stable, deterministic identifier formed from the grouping\n        dimensions (e.g. ``\"code.function::services\"``). Lets the\n        client correlate inter-supernode edges without a separate\n        id resolution round-trip.\n    type: The ``n.type`` value for the dominant member. All\n        members of a supernode share this type — the grouping key\n        includes type as the first dimension.\n    group_key: The non-type portion of the grouping tuple (e.g.\n        ``\"services\"`` for a path-prefix grouping). ``None`` when\n        the grouping is type-only.\n    members_count: Number of underlying live nodes the supernode\n        represents.\n    top_member_names: Up to three node names from the cluster,\n        ranked by ``importance_score`` desc. Lets the renderer\n        render meaningful labels without expanding the cluster.\n    aggregate_importance: Sum of ``importance_score`` across all\n        members. Drives client-side prominence ranking — the\n        renderer can sort or size supernodes by this value.\n    x: Optional pre-computed layout x-coordinate. Always ``None``\n        in Phase A; populated by the layout-precompute job in\n        Phase B so the renderer skips force-directed layout for\n        workspaces that have it cached. The frontend can read\n        this property today and treat ``None`` as \"compute\n        client-side\".\n    y: Optional pre-computed layout y-coordinate. Same Phase B\n        shape contract as ``x``."},"GraphStatsConnectionRow":{"properties":{"id":{"type":"string","title":"Id"},"label":{"type":"string","title":"Label"},"nodes":{"type":"integer","title":"Nodes"},"edges":{"type":"integer","title":"Edges"}},"type":"object","required":["id","label","nodes","edges"],"title":"GraphStatsConnectionRow","description":"Per-connection node + edge counts for the by-connection chart.\n\nEdges are attributed to the source node's connection (Neo4j edges\ndon't carry ``connection_id`` directly). Nodes without a\nconnection are bucketed under the synthetic ``id=\"_manual\"`` row\nwith ``label=\"Manual / system\"`` so they still appear in the\nrendered breakdown."},"GraphStatsConnectivity":{"properties":{"connected":{"type":"integer","title":"Connected"},"orphan":{"type":"integer","title":"Orphan"}},"type":"object","required":["connected","orphan"],"title":"GraphStatsConnectivity","description":"Counts of connected (degree>0) vs orphan (degree=0) nodes.\n\nSums to ``total_node_count``. Drives the connectivity donut in\nthe StatsPanel."},"GraphStatsCountedSlice":{"properties":{"name":{"type":"string","title":"Name"},"value":{"type":"integer","title":"Value"}},"type":"object","required":["name","value"],"title":"GraphStatsCountedSlice","description":"One ``(name, value)`` pair in a graph-stats distribution.\n\nUsed for the ``nodes_by_type`` and ``edges_by_type`` rollups. The\nlist is ordered desc by ``value`` so the renderer can surface the\ntop-N slices without a second sort."},"GraphStatsDegreeBin":{"properties":{"label":{"type":"string","title":"Label"},"value":{"type":"integer","title":"Value"}},"type":"object","required":["label","value"],"title":"GraphStatsDegreeBin","description":"One bucket in the degree-distribution histogram.\n\nBin labels follow the StatsPanel's existing layout\n(``\"0\"``, ``\"1\"``, ``\"2\"``, ``\"3-5\"``, ``\"6-10\"``, ``\"11+\"``)\nso the consumer can render without a translation table."},"GraphStatsHubRow":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"label":{"type":"string","title":"Label"},"type":{"type":"string","title":"Type"},"degree":{"type":"integer","title":"Degree"}},"type":"object","required":["id","label","type","degree"],"title":"GraphStatsHubRow","description":"One node in the top-hubs ranking.\n\n``degree`` is the count of incident edges (in + out) on the node.\nThe renderer draws a horizontal bar chart of the top-N rows so\nusers can spot dominant nodes at a glance."},"GraphStatsRecord":{"properties":{"total_node_count":{"type":"integer","title":"Total Node Count","default":0},"total_edge_count":{"type":"integer","title":"Total Edge Count","default":0},"nodes_by_type":{"items":{"$ref":"#/components/schemas/GraphStatsCountedSlice"},"type":"array","title":"Nodes By Type"},"edges_by_type":{"items":{"$ref":"#/components/schemas/GraphStatsCountedSlice"},"type":"array","title":"Edges By Type"},"by_connection":{"items":{"$ref":"#/components/schemas/GraphStatsConnectionRow"},"type":"array","title":"By Connection"},"top_hubs":{"items":{"$ref":"#/components/schemas/GraphStatsHubRow"},"type":"array","title":"Top Hubs"},"degree_distribution":{"items":{"$ref":"#/components/schemas/GraphStatsDegreeBin"},"type":"array","title":"Degree Distribution"},"connectivity":{"$ref":"#/components/schemas/GraphStatsConnectivity"},"density":{"type":"number","title":"Density","default":0.0}},"type":"object","title":"GraphStatsRecord","description":"Workspace-level graph-health rollup for the StatsPanel.\n\nReturned by :meth:`OntologyRepository.graph_stats`. Computed\nserver-side over the entire workspace graph (not the currently-\nrendered subset) so the panel reports overall graph health rather\nthan an artefact of the user's current drill-down or filter.\n\nAll eight UI boxes derive from this single payload. Counts include\nonly live (non-deleted) nodes and edges.\n\nAttributes:\n    total_node_count: Total live nodes in the workspace.\n    total_edge_count: Total live edges in the workspace.\n    nodes_by_type: ``[{name, value}]`` distribution of nodes by\n        ``n.type``, ordered desc by count.\n    edges_by_type: ``[{name, value}]`` distribution of edges by\n        relationship type, ordered desc by count.\n    by_connection: Per-connection node + edge counts. Synthetic\n        ``\"_manual\"`` row covers nodes without a connection.\n    top_hubs: Top-N highest-degree nodes (in + out edges). The\n        provider caps N at 5 to keep the chart legible.\n    degree_distribution: Histogram of node degrees binned into\n        ``\"0\"`` / ``\"1\"`` / ``\"2\"`` / ``\"3-5\"`` / ``\"6-10\"`` /\n        ``\"11+\"``.\n    connectivity: Connected (degree>0) vs orphan (degree=0)\n        node counts.\n    density: Edges / max-possible edges in an undirected complete\n        graph: ``edges / (n*(n-1)/2)``. Range ``[0, 1]``. ``0``\n        for graphs with fewer than 2 nodes."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HybridSearchRequest":{"properties":{"q":{"type":"string","maxLength":2000,"minLength":1,"title":"Q","description":"Natural-language or keyword query string."},"top_k":{"type":"integer","maximum":50.0,"minimum":1.0,"title":"Top K","description":"Maximum number of nodes to return.","default":20},"mode":{"type":"string","enum":["vector","structural","hybrid"],"title":"Mode","description":"Retrieval strategy.","default":"hybrid"},"filters":{"additionalProperties":true,"type":"object","title":"Filters","description":"Optional filter dict (e.g. {'type': ['person']})."}},"type":"object","required":["q"],"title":"HybridSearchRequest","description":"Body for POST /ontology/search.\n\nAttributes:\n    q: Natural-language query string.\n    top_k: Max number of results to return. Capped at 50.\n    mode: Retrieval strategy. Defaults to ``hybrid``.\n    filters: Optional filter dict. Supported keys:\n        * ``type``: list of node type strings to include."},"HybridSearchResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/ScoredNodeResponse"},"type":"array","title":"Results","description":"Matched nodes with scores, ordered best-first."},"mode":{"type":"string","title":"Mode","description":"Retrieval mode actually used."},"query_plan":{"additionalProperties":true,"type":"object","title":"Query Plan","description":"Introspection of how the query was executed: weights, counts, filters applied."},"credit_receipt":{"$ref":"#/components/schemas/CreditReceiptResponse","description":"Credit charge attached to this call."}},"type":"object","required":["results","mode","credit_receipt"],"title":"HybridSearchResponse","description":"Response body for POST /ontology/search."},"LatencyPercentiles":{"properties":{"p50_ms":{"type":"integer","title":"P50 Ms"},"p95_ms":{"type":"integer","title":"P95 Ms"},"p99_ms":{"type":"integer","title":"P99 Ms"}},"type":"object","required":["p50_ms","p95_ms","p99_ms"],"title":"LatencyPercentiles","description":"Dispatcher latency percentiles in milliseconds."},"McpTokenCreateBody":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name","description":"Human-readable label for this token (e.g. 'Cursor dev machine'). Shown in the Settings token list."},"expires_days":{"anyOf":[{"type":"integer","maximum":365.0,"minimum":1.0},{"type":"null"}],"title":"Expires Days","description":"Token TTL in days. Defaults to 90 days. Capped at 365.","default":90}},"type":"object","required":["name"],"title":"McpTokenCreateBody","description":"Request body for POST /v1/workspaces/{ws}/mcp-tokens."},"McpTokenCreateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"token_prefix":{"type":"string","title":"Token Prefix"},"audience":{"type":"string","title":"Audience"},"scopes":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Scopes"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"last_used_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Used Ip"},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Revoked At"},"request_count":{"type":"integer","title":"Request Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"plaintext":{"type":"string","title":"Plaintext","description":"Full bearer token — shown once at creation. Paste into your IDE MCP config as ``Authorization: Bearer <token>``."}},"type":"object","required":["id","name","workspace_id","token_prefix","audience","scopes","expires_at","last_used_at","last_used_ip","revoked_at","request_count","created_at","plaintext"],"title":"McpTokenCreateResponse","description":"Create response — extends ``ApiKeyRow`` with a one-time plaintext."},"MemoryAttachRequest":{"properties":{"related_node_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":32,"minItems":1,"title":"Related Node Ids","description":"Additional workspace node ids to link the memory to."}},"type":"object","required":["related_node_ids"],"title":"MemoryAttachRequest","description":"Body for POST /memories/{id}/attach."},"MemoryDetailResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"kind":{"type":"string","title":"Kind"},"auto_score":{"type":"number","title":"Auto Score"},"operator_weight":{"type":"number","title":"Operator Weight"},"effective_score":{"type":"number","title":"Effective Score"},"is_pinned":{"type":"boolean","title":"Is Pinned"},"reason":{"type":"string","title":"Reason"},"fields":{"additionalProperties":true,"type":"object","title":"Fields"}},"type":"object","required":["id","kind","auto_score","operator_weight","effective_score","is_pinned","reason","fields"],"title":"MemoryDetailResponse","description":"Fully resolved detail for one memory node.\n\nAttributes:\n    id: Memory node UUID.\n    kind: procedural / episodic / semantic.\n    auto_score: System-computed baseline score.\n    operator_weight: Operator adjustment in [-1, +1].\n    effective_score: Combined score.\n    is_pinned: Whether this memory is pinned.\n    reason: Last audit note.\n    fields: Kind-specific property dict."},"MemoryForgetInput":{"properties":{"memory_id":{"type":"string","format":"uuid","title":"Memory Id","description":"UUID of the Episode or Procedure to soft-delete."},"require_grant":{"type":"boolean","title":"Require Grant","description":"Set true to acknowledge deletion of pinned or tenant-policy memories. Without this flag the call raises a permission error on protected rows.","default":false}},"additionalProperties":false,"type":"object","required":["memory_id"],"title":"MemoryForgetInput","description":"Input for ``memory.forget`` (SPEC §6.4)."},"MemoryForgetOutput":{"properties":{"forgotten":{"type":"boolean","title":"Forgotten","description":"True when the node was soft-deleted; False when it was not found or already deleted."}},"type":"object","required":["forgotten"],"title":"MemoryForgetOutput","description":"Result of a ``memory.forget`` call."},"MemoryListItemRow":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"kind":{"type":"string","title":"Kind"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"auto_score":{"type":"number","title":"Auto Score"},"operator_weight":{"type":"number","title":"Operator Weight"},"effective_score":{"type":"number","title":"Effective Score"},"is_pinned":{"type":"boolean","title":"Is Pinned"},"last_recalled_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Recalled At"},"recall_count_7d":{"type":"integer","title":"Recall Count 7D","default":0}},"type":"object","required":["id","kind","title","auto_score","operator_weight","effective_score","is_pinned"],"title":"MemoryListItemRow","description":"Serialisable projection of a MemoryListItem.\n\nAttributes:\n    id: Neo4j node UUID.\n    kind: semantic / episodic / procedural.\n    title: Human-readable label.\n    auto_score: System-computed baseline score.\n    operator_weight: Operator-supplied weight override.\n    effective_score: Effective combined score.\n    is_pinned: Whether the operator has pinned this memory.\n    last_recalled_at: ISO timestamp or None.\n    recall_count_7d: Rolling 7-day recall count."},"MemoryListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/MemoryListItemRow"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["items"],"title":"MemoryListResponse","description":"Paginated memory list envelope.\n\nAttributes:\n    items: Memory rows for this page.\n    next_cursor: Opaque continuation token; None when last page."},"MemoryProcedureForInput":{"properties":{"trigger":{"type":"string","maxLength":512,"minLength":1,"title":"Trigger","description":"Exact ``trigger_pattern`` string to look up. Pass the canonical form the writer stamped at promotion time."}},"additionalProperties":false,"type":"object","required":["trigger"],"title":"MemoryProcedureForInput","description":"Input for ``memory.procedure_for`` (SPEC §6.4)."},"MemoryProcedureForOutput":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id","description":"Procedure UUID, or null when no match was found."},"trigger":{"type":"string","title":"Trigger","description":"The trigger pattern that was looked up."},"instruction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instruction","description":"Procedure instruction text, or null on miss."},"confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Confidence","description":"Precision score ``[0, 1]``, or null on miss."},"invalidated":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Invalidated","description":"True when the Procedure is flagged for review; null on miss."},"procedure":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Procedure","description":"Full Procedure dict when found; null on miss."}},"type":"object","required":["id","trigger"],"title":"MemoryProcedureForOutput","description":"Result of a ``memory.procedure_for`` call.\n\nWhen no Procedure matches, ``id`` is ``None`` and the other\nfields are absent. The agent should fall back to\n``memory.recall`` when ``id`` is null."},"MemoryRecallInput":{"properties":{"intent":{"type":"string","maxLength":2048,"title":"Intent","description":"Natural-language description of what the agent is trying to do. Drives ranking; structural anchors narrow the scope."},"symbol_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Symbol Id","description":"Optional ``code.symbol`` UUID to anchor recall on. When set the recall returns only procedures + episodes tied to this symbol."},"outcome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outcome","description":"Optional outcome filter: ``succeeded``, ``failed``, or ``abandoned``. ``failed`` is most useful for retrieving recovery procedures."},"limit":{"type":"integer","maximum":50.0,"minimum":1.0,"title":"Limit","description":"Max procedures + max episodes returned. Default 10.","default":10}},"additionalProperties":false,"type":"object","required":["intent"],"title":"MemoryRecallInput","description":"Input for ``memory.recall`` (SPEC §6.4)."},"MemoryRecallOutput":{"properties":{"procedures":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Procedures","description":"Procedures matching the scope, ranked by effective score descending."},"episodes":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Episodes","description":"Episodes matching the scope, ranked by effective score descending."}},"type":"object","title":"MemoryRecallOutput","description":"SPEC §6.4 recall envelope."},"MemoryRememberInput":{"properties":{"fact":{"type":"string","maxLength":4096,"minLength":1,"title":"Fact","description":"Free-form text the agent wants the memory module to store. Persisted as a graph Episode summary."},"session_id":{"type":"string","format":"uuid","title":"Session Id","description":"Active ``agent.session`` UUID. The memory module anchors the new Episode to this session so subsequent recall calls can structurally retrieve it."},"kind":{"type":"string","title":"Kind","description":"Memory kind. Only ``episode`` is supported in M8; ``procedure`` is reserved for the promotion pipeline.","default":"episode"},"outcome":{"type":"string","title":"Outcome","description":"Outcome to stamp on the Episode: ``succeeded`` (default), ``failed``, or ``abandoned``. ``failed`` plus ``error_signature`` makes the Episode participate in the M8 promotion pipeline.","default":"succeeded"},"error_signature":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Error Signature","description":"Normalised error string for the SPEC §6.2 cluster anchor. Required alongside ``outcome=failed`` for the Episode to participate in failure clustering."},"triggering_symbol_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Triggering Symbol Id","description":"Optional ``code.symbol`` UUID the agent was working on. Promoted to the SPEC §6.2 cluster anchor."}},"additionalProperties":false,"type":"object","required":["fact","session_id"],"title":"MemoryRememberInput","description":"Input for ``memory.remember`` (SPEC §6.4)."},"MemoryRememberOutput":{"properties":{"id":{"type":"string","title":"Id","description":"UUID of the newly created memory node."},"kind":{"type":"string","title":"Kind","description":"Kind of memory stored (``episode``)."}},"type":"object","required":["id","kind"],"title":"MemoryRememberOutput","description":"Result of a successful ``memory.remember`` call."},"MemoryResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"title":{"type":"string","title":"Title"},"content":{"type":"string","title":"Content"},"kind":{"type":"string","title":"Kind"},"agent_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Id"},"conversation_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Conversation Id"},"author_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Author User Id"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"related_node_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Related Node Ids"},"recorded_at":{"type":"string","title":"Recorded At"}},"type":"object","required":["id","workspace_id","title","content","kind","agent_id","conversation_id","author_user_id","tags","related_node_ids","recorded_at"],"title":"MemoryResponse","description":"Public projection of a work memory."},"MintMCPTokenRequest":{"properties":{"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id","description":"Workspace the token authorizes access to."},"expires_in_days":{"type":"integer","maximum":365.0,"minimum":1.0,"title":"Expires In Days","description":"Token TTL in days. Capped at 365 so a stolen token self-expires within a bounded window.","default":30}},"type":"object","required":["workspace_id"],"title":"MintMCPTokenRequest","description":"Body for ``POST /v1/mcp/token``."},"MintMCPTokenResponse":{"properties":{"token":{"type":"string","title":"Token"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"expires_in_days":{"type":"integer","title":"Expires In Days"}},"type":"object","required":["token","workspace_id","expires_in_days"],"title":"MintMCPTokenResponse","description":"Response body — the minted JWT + echoed lifetime."},"ModelConfigUpdate":{"properties":{"level_1":{"type":"string","title":"Level 1","description":"Model for Level 1 (Oxagen). Pass ``'oxagen-managed'`` to revert to the platform default.","default":"oxagen-managed"},"level_2":{"type":"string","title":"Level 2","description":"Model for Level 2 (Oxagen+).","default":"oxagen-managed"},"level_3":{"type":"string","title":"Level 3","description":"Model for Level 3 (Oxagen+ Pro).","default":"oxagen-managed"},"embedding":{"type":"string","title":"Embedding","description":"Embedding model for this workspace.","default":"oxagen-managed"}},"type":"object","title":"ModelConfigUpdate","description":"Body for PATCH /workspace-models/workspace/model-config.\n\nEach field maps a tier (or ``\"embedding\"``) to either\n``\"oxagen-managed\"`` (uses platform defaults) or a model ID from\nthe registry. Unknown model IDs are rejected 422.\n\nAttributes:\n    level_1: Model selection for Level 1 (Oxagen tier).\n    level_2: Model selection for Level 2 (Oxagen+ tier).\n    level_3: Model selection for Level 3 (Oxagen+ Pro tier).\n    embedding: Model selection for embedding calls."},"ModelProvider":{"type":"string","enum":["anthropic","openai","google","xai","mistral"],"title":"ModelProvider","description":"Supported BYOK providers.\n\nAnthropic + OpenAI shipped in Phase 2. Google, xAI, and Mistral\nwere added in OXA-931 Wave 4. The table and API accept any value\nthe validator dispatcher knows about — adding a new provider is a\nmatter of adding an enum entry + a validator + a provider class."},"NodeCitationResponse":{"properties":{"node_id":{"type":"string","format":"uuid","title":"Node Id","description":"Cited node UUID."},"type":{"type":"string","title":"Type","description":"Cited node type."},"name":{"type":"string","title":"Name","description":"Cited node name."},"excerpt":{"type":"string","title":"Excerpt","description":"Short excerpt the answerer chose to justify the citation."}},"type":"object","required":["node_id","type","name","excerpt"],"title":"NodeCitationResponse","description":"Projection of a cited node in an answer."},"NodeCreateRequest":{"properties":{"type":{"type":"string","maxLength":80,"pattern":"^[a-z][a-z0-9_.]*$","title":"Type","description":"Node type identifier. Lowercase, optionally dot-namespaced (e.g. 'person', 'code.function') — must match [a-z][a-z0-9_.]*. Auto-registered in ontology.types."},"name":{"type":"string","maxLength":500,"minLength":1,"title":"Name","description":"Human-readable node name, 1-500 chars."},"properties":{"additionalProperties":true,"type":"object","title":"Properties","description":"Free-form JSONB properties attached to the node."},"connection_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Connection Id","description":"Optional FK to connections.id when the node was imported from a data source."}},"type":"object","required":["type","name"],"title":"NodeCreateRequest","description":"Body for POST /ontology/nodes."},"NodeResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"Node UUID primary key."},"type":{"type":"string","title":"Type","description":"Node type identifier."},"name":{"type":"string","title":"Name","description":"Human-readable node name."},"properties":{"additionalProperties":true,"type":"object","title":"Properties","description":"Free-form JSONB properties."},"connection_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Connection Id","description":"FK to connections.id, or null for prompt entries."},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id","description":"Workspace UUID owning this node."},"created_at":{"type":"string","title":"Created At","description":"ISO-8601 timestamp of creation (UTC)."},"has_embedding":{"type":"boolean","title":"Has Embedding","description":"True when the embedding column is populated by the worker."}},"type":"object","required":["id","type","name","properties","connection_id","workspace_id","created_at","has_embedding"],"title":"NodeResponse","description":"Public projection of a Node row (embedding omitted — it's big)."},"NodeSearchRequest":{"properties":{"query":{"type":"string","maxLength":2000,"minLength":1,"title":"Query","description":"Natural-language query to embed and match."},"limit":{"type":"integer","maximum":50.0,"minimum":1.0,"title":"Limit","description":"Maximum number of nodes to return (1-50).","default":10},"type":{"anyOf":[{"type":"string","maxLength":80,"pattern":"^[a-z][a-z0-9_.]*$"},{"type":"null"}],"title":"Type","description":"Optional node type filter (exact match, snake_case)."}},"type":"object","required":["query"],"title":"NodeSearchRequest","description":"Body for POST /ontology/nodes/search."},"OntologyAskInput":{"properties":{"prompt":{"type":"string","maxLength":8000,"minLength":1,"title":"Prompt","description":"The question to ask over your workspace ontology."},"top_k":{"type":"integer","maximum":100.0,"minimum":1.0,"title":"Top K","description":"Max candidate nodes to consider during retrieval. Higher values improve recall at the cost of a larger LLM context.","default":20}},"additionalProperties":false,"type":"object","required":["prompt"],"title":"OntologyAskInput","description":"Input for ``ontology.ask``."},"OntologyAskOutput":{"properties":{"narrative":{"type":"string","title":"Narrative","description":"Grounded answer narrative. Every factual claim is tied to a cited node UUID."},"citations":{"items":{"$ref":"#/components/schemas/CitationProjection"},"type":"array","title":"Citations","description":"Nodes cited in the narrative."},"candidate_count":{"type":"integer","title":"Candidate Count","description":"Retrieval candidate count before LLM filtering.","default":0},"retrieval_mode":{"type":"string","title":"Retrieval Mode","description":"Retrieval mode used by the pipeline.","default":"hybrid"}},"type":"object","required":["narrative"],"title":"OntologyAskOutput","description":"Response from ``ontology.ask``."},"OntologyDeleteEdgeInput":{"properties":{"edge_id":{"type":"string","format":"uuid","title":"Edge Id","description":"UUID of the edge to soft-delete."},"confirmation":{"type":"string","title":"Confirmation","description":"Typed confirmation sentinel. Must equal 'CONFIRMED' (case-sensitive). Ask the user to confirm by typing CONFIRMED before invoking this destructive tool."}},"additionalProperties":false,"type":"object","required":["edge_id","confirmation"],"title":"OntologyDeleteEdgeInput","description":"Input for soft-deleting an edge."},"OntologyDeleteEdgeOutput":{"properties":{"edge_id":{"type":"string","format":"uuid","title":"Edge Id","description":"UUID of the soft-deleted edge."},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id","description":"Workspace UUID that owned the edge."},"deleted":{"type":"boolean","title":"Deleted","description":"Always True on success.","default":true},"edge_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Edge Type","description":"Type tag of the deleted edge."},"source_node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Source Node Id","description":"Source node UUID of the deleted edge."},"target_node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Target Node Id","description":"Target node UUID of the deleted edge."}},"type":"object","required":["edge_id","workspace_id"],"title":"OntologyDeleteEdgeOutput","description":"Result of a successful edge soft-delete."},"OntologyDeleteNodeInput":{"properties":{"node_id":{"type":"string","format":"uuid","title":"Node Id","description":"UUID of the node to soft-delete."},"cascade_edges":{"type":"boolean","title":"Cascade Edges","description":"When true (default) also soft-delete all incident edges whose source or target is this node.","default":true},"confirmation":{"type":"string","title":"Confirmation","description":"Typed confirmation sentinel. Must equal 'CONFIRMED' (case-sensitive). Ask the user to confirm by typing CONFIRMED before invoking this destructive tool."}},"additionalProperties":false,"type":"object","required":["node_id","confirmation"],"title":"OntologyDeleteNodeInput","description":"Input for soft-deleting a node."},"OntologyDeleteNodeOutput":{"properties":{"node_id":{"type":"string","format":"uuid","title":"Node Id","description":"UUID of the soft-deleted node."},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id","description":"Workspace UUID that owned the node."},"deleted":{"type":"boolean","title":"Deleted","description":"Always True on success.","default":true},"cascade_edges":{"type":"boolean","title":"Cascade Edges","description":"Whether incident edges were also soft-deleted."},"node_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Type","description":"Type tag of the deleted node."},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name","description":"Display name of the deleted node."}},"type":"object","required":["node_id","workspace_id","cascade_edges"],"title":"OntologyDeleteNodeOutput","description":"Result of a successful node soft-delete."},"OntologyDeleteNodesByTypeInput":{"properties":{"node_type":{"type":"string","maxLength":80,"minLength":1,"title":"Node Type","description":"Ontology type tag whose nodes should be soft-deleted (e.g. ``\"person\"``, ``\"code.file\"``). Type catalog rows are NOT deleted — use ``ontology.delete_type`` for that."},"confirmation":{"type":"string","title":"Confirmation","description":"Typed confirmation sentinel. Must equal 'CONFIRMED' (case-sensitive). Ask the user to confirm by typing CONFIRMED before invoking this destructive tool — it wipes every matching node and their incident edges."}},"additionalProperties":false,"type":"object","required":["node_type","confirmation"],"title":"OntologyDeleteNodesByTypeInput","description":"Input for soft-deleting every node of a given type."},"OntologyDeleteNodesByTypeOutput":{"properties":{"node_type":{"type":"string","title":"Node Type","description":"The type whose nodes were deleted."},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id","description":"Workspace UUID where the cascade ran."},"deleted_nodes":{"type":"integer","title":"Deleted Nodes","description":"Count of nodes soft-deleted by the cascade."},"deleted_edges":{"type":"integer","title":"Deleted Edges","description":"Count of incident edges soft-deleted alongside the nodes."}},"type":"object","required":["node_type","workspace_id","deleted_nodes","deleted_edges"],"title":"OntologyDeleteNodesByTypeOutput","description":"Result of a successful bulk-by-type soft-delete."},"OntologyDeleteTypeInput":{"properties":{"name":{"type":"string","maxLength":80,"minLength":1,"title":"Name","description":"Type name to delete (e.g. ``\"person\"``). Must be a live type in the workspace catalog."},"kind":{"type":"string","enum":["node","edge"],"title":"Kind","description":"Either ``\"node\"`` or ``\"edge\"``.","default":"node"},"confirmation":{"type":"string","title":"Confirmation","description":"Typed confirmation sentinel. Must equal 'CONFIRMED' (case-sensitive). Ask the user to confirm by typing CONFIRMED before invoking this destructive tool."}},"additionalProperties":false,"type":"object","required":["name","confirmation"],"title":"OntologyDeleteTypeInput","description":"Input for deleting a type."},"OntologyDeleteTypeOutput":{"properties":{"name":{"type":"string","title":"Name","description":"The type name that was deleted."},"kind":{"type":"string","title":"Kind","description":"Whether this was a node or edge type."},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id","description":"Workspace UUID where the type was deleted."},"deleted":{"type":"boolean","title":"Deleted","description":"Always True on success.","default":true},"cascade_count":{"type":"integer","title":"Cascade Count","description":"Number of nodes (or edges) soft-deleted as part of the cascade."}},"type":"object","required":["name","kind","workspace_id","cascade_count"],"title":"OntologyDeleteTypeOutput","description":"Result of a successful type deletion."},"OntologyExplainFunctionInput":{"properties":{"name":{"type":"string","minLength":1,"title":"Name","description":"Function name to explain."}},"additionalProperties":false,"type":"object","required":["name"],"title":"OntologyExplainFunctionInput","description":"Input for ``ontology.explain_function``."},"OntologyExplainFunctionOutput":{"properties":{"function":{"anyOf":[{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_explain_function___FunctionBrief"},{"type":"null"}],"description":"The resolved function node."},"calls":{"items":{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_explain_function___NodeBrief"},"type":"array","title":"Calls","description":"Functions this function calls."},"throws":{"items":{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_explain_function___NodeBrief"},"type":"array","title":"Throws","description":"Exceptions this function throws."},"reads":{"items":{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_explain_function___NodeBrief"},"type":"array","title":"Reads","description":"Symbols this function reads."},"writes":{"items":{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_explain_function___NodeBrief"},"type":"array","title":"Writes","description":"Symbols this function writes."},"returns":{"items":{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_explain_function___NodeBrief"},"type":"array","title":"Returns","description":"Semantic return types."},"tested_by":{"items":{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_explain_function___NodeBrief"},"type":"array","title":"Tested By","description":"Test functions that cover this function."},"recent_commits":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Recent Commits","description":"Recent commits that touched this function."},"error":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Error","description":"Set when the function was not found. Keys: code, message, name."}},"type":"object","title":"OntologyExplainFunctionOutput","description":"Cookbook JSON envelope for ``ontology.explain_function``."},"OntologyFamilyTreeInput":{"properties":{"target_id":{"type":"string","format":"uuid","title":"Target Id","description":"UUID of the center node to expand from. Must live in the caller's workspace."},"degrees_of_separation":{"type":"integer","maximum":5.0,"minimum":1.0,"title":"Degrees Of Separation","description":"Hops to expand outward. 1 = direct neighbors; 2 = neighbors of neighbors; up to 5. Default 2.","default":2},"node_limit":{"type":"integer","maximum":5000.0,"minimum":10.0,"title":"Node Limit","description":"Cap on total nodes returned (including center). Default 500.","default":500},"edge_limit":{"type":"integer","maximum":10000.0,"minimum":10.0,"title":"Edge Limit","description":"Cap on edges returned. Default 1000.","default":1000}},"additionalProperties":false,"type":"object","required":["target_id"],"title":"OntologyFamilyTreeInput","description":"Input for ``ontology.family_tree``.\n\nIdentity (workspace_id, user_id) is derived from the caller's\nbearer token, never from input — OXA-387 identity contract."},"OntologyFamilyTreeOutput":{"properties":{"center":{"anyOf":[{"$ref":"#/components/schemas/_NodeProjection"},{"type":"null"}],"description":"The center node of the family tree."},"nodes":{"items":{"$ref":"#/components/schemas/_NodeProjection"},"type":"array","title":"Nodes","description":"All nodes within degrees_of_separation hops, including center."},"edges":{"items":{"$ref":"#/components/schemas/_EdgeProjection"},"type":"array","title":"Edges","description":"All live edges between nodes in the result set."},"degrees_of_separation":{"type":"integer","title":"Degrees Of Separation","description":"Degrees of separation requested."},"node_count":{"type":"integer","title":"Node Count","description":"Total nodes in result (len(nodes))."},"edge_count":{"type":"integer","title":"Edge Count","description":"Total edges in result (len(edges))."},"error":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Error","description":"Set when the center node was not found. Keys: code, message."}},"type":"object","required":["degrees_of_separation","node_count","edge_count"],"title":"OntologyFamilyTreeOutput","description":"Result of ``ontology.family_tree``."},"OntologyGetEdgeInput":{"properties":{"edge_id":{"type":"string","format":"uuid","title":"Edge Id","description":"UUID of the edge to fetch."}},"additionalProperties":false,"type":"object","required":["edge_id"],"title":"OntologyGetEdgeInput","description":"Input — the edge id to fetch."},"OntologyGetEdgeOutput":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"Edge UUID primary key."},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id","description":"Workspace UUID owning the edge."},"source_node_id":{"type":"string","format":"uuid","title":"Source Node Id","description":"Originating node UUID."},"target_node_id":{"type":"string","format":"uuid","title":"Target Node Id","description":"Destination node UUID."},"type":{"type":"string","title":"Type","description":"Edge type identifier."},"properties":{"additionalProperties":true,"type":"object","title":"Properties","description":"Free-form JSONB properties on the edge."},"weight":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Weight","description":"Optional relationship weight."},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At","description":"ISO-8601 timestamp of creation (UTC), or null."}},"type":"object","required":["id","workspace_id","source_node_id","target_node_id","type"],"title":"OntologyGetEdgeOutput","description":"Resolved edge projection."},"OntologyImpactOfInput":{"properties":{"name":{"type":"string","minLength":1,"title":"Name","description":"Symbol name to analyse."}},"additionalProperties":false,"type":"object","required":["name"],"title":"OntologyImpactOfInput","description":"Input for ``ontology.impact_of``."},"OntologyImpactOfOutput":{"properties":{"symbol":{"anyOf":[{"$ref":"#/components/schemas/_SymbolBrief"},{"type":"null"}],"description":"The resolved symbol node."},"reads":{"items":{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_impact_of___NodeBrief"},"type":"array","title":"Reads","description":"Functions that read this symbol."},"writes":{"items":{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_impact_of___NodeBrief"},"type":"array","title":"Writes","description":"Functions that write this symbol."},"modifies":{"items":{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_impact_of___NodeBrief"},"type":"array","title":"Modifies","description":"Functions that modify this symbol."},"calculates":{"items":{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_impact_of___NodeBrief"},"type":"array","title":"Calculates","description":"Functions that calculate this symbol."},"error":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Error","description":"Set when the symbol was not found. Keys: code, message, name."}},"type":"object","title":"OntologyImpactOfOutput","description":"Inbound-traversal envelope for ``ontology.impact_of``."},"OntologyRenameTypeInput":{"properties":{"from_name":{"type":"string","maxLength":80,"minLength":1,"title":"From Name","description":"Current type name (e.g. ``\"person\"``). Must be a live type in the workspace catalog."},"to_name":{"type":"string","maxLength":80,"minLength":1,"title":"To Name","description":"Target type name (e.g. ``\"contact\"``). Must not already exist as a live type in the workspace."},"kind":{"type":"string","enum":["node","edge"],"title":"Kind","description":"Either ``\"node\"`` or ``\"edge\"``.","default":"node"}},"additionalProperties":false,"type":"object","required":["from_name","to_name"],"title":"OntologyRenameTypeInput","description":"Input for renaming a type."},"OntologyRenameTypeOutput":{"properties":{"from_name":{"type":"string","title":"From Name","description":"The original type name that was renamed."},"to_name":{"type":"string","title":"To Name","description":"The new type name."},"kind":{"type":"string","title":"Kind","description":"Whether this was a node or edge type."},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id","description":"Workspace UUID where the rename was applied."},"affected_count":{"type":"integer","title":"Affected Count","description":"Number of nodes (or edges) whose type field was updated."}},"type":"object","required":["from_name","to_name","kind","workspace_id","affected_count"],"title":"OntologyRenameTypeOutput","description":"Result of a successful type rename."},"OntologySearchInput":{"properties":{"q":{"type":"string","maxLength":2000,"minLength":1,"title":"Q","description":"Natural-language or keyword query string."},"top_k":{"type":"integer","maximum":50.0,"minimum":1.0,"title":"Top K","description":"Maximum number of nodes to return (1-50).","default":20},"mode":{"type":"string","enum":["vector","structural","hybrid"],"title":"Mode","description":"Retrieval strategy.","default":"hybrid"},"filters":{"additionalProperties":true,"type":"object","title":"Filters","description":"Optional filter dict. Supported keys: 'type' (list of node type strings to include)."}},"additionalProperties":false,"type":"object","required":["q"],"title":"OntologySearchInput","description":"Input — query, mode, top_k, and optional filters."},"OntologySearchOutput":{"properties":{"results":{"items":{"$ref":"#/components/schemas/ScoredNodeProjection"},"type":"array","title":"Results","description":"Matched nodes ordered best-first."},"mode":{"type":"string","title":"Mode","description":"Retrieval mode actually used."},"query_plan":{"additionalProperties":true,"type":"object","title":"Query Plan","description":"Introspection — weights, counts, and filters applied."}},"type":"object","required":["mode"],"title":"OntologySearchOutput","description":"Response — ranked nodes plus the query plan."},"OntologySymbolContextInput":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Display name to resolve. Tried against code.function, code.class, then code.symbol in cookbook order."},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id","description":"Direct UUID of the target node. Use when the caller already holds an id from a prior call."},"siblings_limit":{"type":"integer","maximum":500.0,"minimum":1.0,"title":"Siblings Limit","description":"Cap on returned sibling methods.","default":50},"tests_limit":{"type":"integer","maximum":500.0,"minimum":1.0,"title":"Tests Limit","description":"Cap on returned test functions.","default":50},"callers_limit":{"type":"integer","maximum":500.0,"minimum":1.0,"title":"Callers Limit","description":"Cap on returned callers.","default":50},"callees_limit":{"type":"integer","maximum":500.0,"minimum":1.0,"title":"Callees Limit","description":"Cap on returned callees.","default":50},"returns_limit":{"type":"integer","maximum":500.0,"minimum":1.0,"title":"Returns Limit","description":"Cap on returned semantic-returns nodes.","default":25},"commits_limit":{"type":"integer","maximum":100.0,"minimum":1.0,"title":"Commits Limit","description":"Cap on returned recent-commit rows.","default":10}},"additionalProperties":false,"type":"object","title":"OntologySymbolContextInput","description":"Input for ``ontology.symbol_context``.\n\nPass either ``name`` (resolved via cookbook precedence order:\ncode.function → code.class → code.symbol) or ``node_id``\n(direct UUID lookup, skipping name resolution).  Identity is\nderived from the bearer token, never from input."},"OntologySymbolContextOutput":{"properties":{"target":{"anyOf":[{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_symbol_context___FunctionBrief"},{"type":"null"}],"description":"The resolved center node."},"containing_class":{"anyOf":[{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_symbol_context___NodeBrief"},{"type":"null"}],"description":"Containing class for method targets; None for top-level functions and classes."},"siblings":{"items":{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_symbol_context___NodeBrief"},"type":"array","title":"Siblings","description":"Other methods on the same class."},"tests":{"items":{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_symbol_context___NodeBrief"},"type":"array","title":"Tests","description":"Test functions paired via is_tested_by."},"callers":{"items":{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_symbol_context___NodeBrief"},"type":"array","title":"Callers","description":"Direct callers of the target function."},"callees":{"items":{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_symbol_context___NodeBrief"},"type":"array","title":"Callees","description":"Direct callees of the target function."},"semantic_returns":{"items":{"$ref":"#/components/schemas/oxagen__capabilities__handlers__ontology_symbol_context___NodeBrief"},"type":"array","title":"Semantic Returns","description":"Targets of LLM-inferred returns edges."},"recent_commits":{"items":{"$ref":"#/components/schemas/_CommitBrief"},"type":"array","title":"Recent Commits","description":"Recent commits touching this node, with action + author."},"error":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Error","description":"Set when the target was not found. Keys: code, message, name."}},"type":"object","title":"OntologySymbolContextOutput","description":"Laser-context bundle for ``ontology.symbol_context``."},"PinBody":{"properties":{"reason":{"type":"string","maxLength":500,"minLength":1,"title":"Reason"}},"type":"object","required":["reason"],"title":"PinBody","description":"Body for POST /items/{memory_id}/pin.\n\nAttributes:\n    reason: Non-empty audit note (1-500 chars)."},"PinResponse":{"properties":{"memory_id":{"type":"string","format":"uuid","title":"Memory Id"},"is_pinned":{"type":"boolean","title":"Is Pinned"}},"type":"object","required":["memory_id","is_pinned"],"title":"PinResponse","description":"Response after pin/unpin.\n\nAttributes:\n    memory_id: Target memory UUID.\n    is_pinned: New pin state."},"ProcedureEditBody":{"properties":{"trigger_pattern":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trigger Pattern"},"instruction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instruction"},"suppressed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Suppressed"}},"type":"object","title":"ProcedureEditBody","description":"Body for PATCH /procedures/{procedure_id}.\n\nAttributes:\n    trigger_pattern: Optional new trigger text.\n    instruction: Optional new instruction text.\n    suppressed: Optional suppression flag."},"PromptRequest":{"properties":{"prompt":{"type":"string","maxLength":50000,"minLength":1,"title":"Prompt","description":"Raw user text (markdown, plain text, pasted notes). Never persisted to the audit row — only a SHA-256 hash is kept."},"force_intent":{"anyOf":[{"type":"string","enum":["update","query","both"]},{"type":"null"}],"title":"Force Intent","description":"Optional override that skips intent classification and forces the pipeline branch."},"source":{"type":"string","maxLength":200,"title":"Source","description":"Optional origin label attached to every extracted node and surfaced in events.","default":"prompt-box"}},"type":"object","required":["prompt"],"title":"PromptRequest","description":"Body for POST /ontology/prompt."},"PromptResponse":{"properties":{"intent":{"type":"string","enum":["update","query","both"],"title":"Intent","description":"Classified (or forced) intent that drove the pipeline."},"correlation_id":{"type":"string","format":"uuid","title":"Correlation Id","description":"UUID also echoed via the X-Correlation-Id header. Groups logs, analytics events, and audit rows for this request."},"nodes_created":{"items":{"$ref":"#/components/schemas/ExtractedNodeResponse"},"type":"array","title":"Nodes Created","description":"Nodes persisted from the refiner pass. Empty on a pure 'query' intent."},"edges_created":{"items":{"$ref":"#/components/schemas/ExtractedEdgeResponse"},"type":"array","title":"Edges Created","description":"Edges persisted from the refiner pass. Empty on a pure 'query' intent."},"dropped_edges":{"type":"integer","title":"Dropped Edges","description":"Number of refiner edges dropped because their source or target ref could not be resolved.","default":0},"refiner_confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Refiner Confidence","description":"Refiner self-reported confidence in [0.0, 1.0], when available."},"answer":{"anyOf":[{"$ref":"#/components/schemas/AnswerResponse"},{"type":"null"}],"description":"Question-answerer result on 'query' / 'both' intents. Null for pure 'update'."}},"type":"object","required":["intent","correlation_id"],"title":"PromptResponse","description":"Body for POST /ontology/prompt response."},"PromptStreamRequest":{"properties":{"prompt":{"type":"string","maxLength":50000,"minLength":1,"title":"Prompt","description":"User question to answer over the workspace ontology. Only query intent is supported on this endpoint."},"mode":{"type":"string","title":"Mode","description":"Agent mode — ``instant`` (default) runs once. ``schedule`` (recurring) and ``event`` (trigger-driven) are reserved for the upcoming agent-modes feature and currently return 422. ``loop`` is accepted as a legacy alias for ``schedule``.","default":"instant"},"verbose":{"type":"boolean","title":"Verbose","description":"When True, full tool inputs and outputs are included in SSE step payloads — no 200-char truncation. Full verbatim data is always persisted regardless of this flag; this controls bandwidth to the client only.","default":false},"conversation_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Conversation Id","description":"When set, prior turns from this conversation are loaded and injected into the LLM context so follow-up questions (e.g. 'yes, do it') resolve against the correct prior turn. Omit on the first turn of a brand-new conversation (which has no prior turns to load)."}},"type":"object","required":["prompt"],"title":"PromptStreamRequest","description":"Body for POST /ontology/prompt/stream.\n\nThe ``mode`` field round-trips the agent mode picker in the chat\nUI. Only ``\"instant\"`` is wired end-to-end today; ``\"schedule\"``\nand ``\"event\"`` are accepted by the schema so the frontend can show\na proper \"coming soon\" error rather than silently running an\ninstant query. The route returns 422 for the unwired modes.\n\nFor backwards compatibility the legacy alias ``\"loop\"`` is accepted\nand normalised to ``\"schedule\"`` by the route handler."},"ReceiptCoverage":{"properties":{"transactions_with_receipt":{"type":"integer","minimum":0.0,"title":"Transactions With Receipt"},"transactions_without_receipt":{"type":"integer","minimum":0.0,"title":"Transactions Without Receipt"},"pct_covered":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Pct Covered"}},"additionalProperties":false,"type":"object","required":["transactions_with_receipt","transactions_without_receipt","pct_covered"],"title":"ReceiptCoverage","description":"Receipt-coverage summary across the trip's transactions.\n\nAttributes:\n    transactions_with_receipt: Count of transactions linked to at\n        least one invoice document via ``[:HAS_RECEIPT]``.\n    transactions_without_receipt: Count of transactions with no\n        linked invoice document.\n    pct_covered: Fraction in ``[0.0, 1.0]`` — ``with /\n        (with + without)``. ``0.0`` when no transactions exist at\n        all (the report is then trivially empty, not \"covered\")."},"RecentEventRow":{"properties":{"entry_id":{"type":"string","title":"Entry Id"},"kind":{"type":"string","title":"Kind"},"slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Slug"},"payload":{"additionalProperties":true,"type":"object","title":"Payload"}},"type":"object","required":["entry_id","kind","slug","payload"],"title":"RecentEventRow","description":"Public projection of one event in the recent feed."},"ResolveApprovalRequest":{"properties":{"decision":{"$ref":"#/components/schemas/ApprovalDecision"},"resolution_note":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Resolution Note"}},"additionalProperties":false,"type":"object","required":["decision"],"title":"ResolveApprovalRequest","description":"Body for ``POST /v1/approvals/{id}/resolve``.\n\nAttributes:\n    decision: ``APPROVED`` or ``REJECTED``.\n    resolution_note: Optional human-readable note attached to the\n        resolution (e.g. why a request was rejected)."},"ResolveApprovalResponse":{"properties":{"approval_id":{"type":"string","format":"uuid","title":"Approval Id"},"decision":{"$ref":"#/components/schemas/ApprovalDecision"}},"type":"object","required":["approval_id","decision"],"title":"ResolveApprovalResponse","description":"Response for ``POST /v1/approvals/{id}/resolve``.\n\nAttributes:\n    approval_id: UUID of the resolved ApprovalRequest.\n    decision: The decision that was recorded."},"RunListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/RunResponse"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["items"],"title":"RunListResponse","description":"Paginated response envelope for ``GET /runs``.\n\nThe TS client expects ``{ items, next_cursor }``; returning a bare\nlist silently corrupts the page-state and crashes the list view\nwhen ``runs.length`` is accessed on ``undefined``."},"RunResponse":{"properties":{"id":{"type":"string","title":"Id"},"workspace_id":{"type":"string","title":"Workspace Id"},"prompt":{"type":"string","title":"Prompt"},"output_types":{"items":{"type":"string"},"type":"array","title":"Output Types"},"target_duration_seconds":{"type":"integer","title":"Target Duration Seconds"},"template_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template Id"},"status":{"type":"string","title":"Status"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"document_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Document Id"},"visibility":{"type":"string","title":"Visibility"},"share_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Share Url"},"share_revoked":{"type":"boolean","title":"Share Revoked","default":false},"owner_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Id"},"created_by_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By Id"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"video_signed_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Video Signed Url"},"audio_signed_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Audio Signed Url"},"cover_signed_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cover Signed Url"},"captions_signed_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Captions Signed Url"},"infographic_signed_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Infographic Signed Url"},"progress_context":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Progress Context"}},"type":"object","required":["id","workspace_id","prompt","output_types","target_duration_seconds","template_id","status","error_message","document_id","visibility"],"title":"RunResponse","description":"Serialized :class:`GenerationRun` for the API surface."},"ScoredNodeProjection":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"Node UUID primary key."},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id","description":"Workspace UUID owning this node."},"type":{"type":"string","title":"Type","description":"Node type identifier."},"name":{"type":"string","title":"Name","description":"Human-readable node name."},"properties":{"additionalProperties":true,"type":"object","title":"Properties","description":"Free-form JSONB properties."},"score":{"type":"number","title":"Score","description":"Combined relevance score; higher is better."},"components":{"additionalProperties":{"type":"number"},"type":"object","title":"Components","description":"Per-source score breakdown — typically vector_score, structural_score, and importance_multiplier."}},"type":"object","required":["id","workspace_id","type","name","score"],"title":"ScoredNodeProjection","description":"One scored node in the search result set."},"ScoredNodeResponse":{"properties":{"node":{"$ref":"#/components/schemas/NodeResponse","description":"The matched node (without embedding)."},"score":{"type":"number","title":"Score","description":"Combined relevance score; higher is better."},"components":{"additionalProperties":{"type":"number"},"type":"object","title":"Components","description":"Per-source score breakdown: vector_score, structural_score, importance_multiplier when present."}},"type":"object","required":["node","score"],"title":"ScoredNodeResponse","description":"Public projection of a ``ScoredNode`` for the search response."},"SlugDefPublic":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"name":{"type":"string","title":"Name"},"trigger_kind":{"type":"string","title":"Trigger Kind"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"filter_json":{"additionalProperties":true,"type":"object","title":"Filter Json"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","workspace_id","name","trigger_kind","description","filter_json","created_at","updated_at"],"title":"SlugDefPublic","description":"Public projection of one ``OntologyEventDef`` row."},"SubscribersResponse":{"properties":{"event_def_id":{"type":"string","format":"uuid","title":"Event Def Id"},"event_def_name":{"type":"string","title":"Event Def Name"},"webhooks":{"items":{"$ref":"#/components/schemas/WebhookSubscriberRow"},"type":"array","title":"Webhooks"},"agent_triggers":{"items":{"$ref":"#/components/schemas/AgentTriggerSubscriberRow"},"type":"array","title":"Agent Triggers"}},"type":"object","required":["event_def_id","event_def_name","webhooks","agent_triggers"],"title":"SubscribersResponse","description":"Bundle of subscriber rows scoped to one event definition."},"SymbolContextRequest":{"properties":{"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id","description":"Preferred form — resolved directly via get_node."},"name":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Name","description":"Alternative resolution form — paired with ``type``. Exact name match in the bound workspace."},"type":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Type","description":"Required when ``name`` is set. Restricts the resolver to a single ontology type (``code.function`` / ``code.class`` / ``code.file``)."},"siblings_limit":{"type":"integer","maximum":200.0,"minimum":1.0,"title":"Siblings Limit","default":50},"tests_limit":{"type":"integer","maximum":200.0,"minimum":1.0,"title":"Tests Limit","default":50},"callers_limit":{"type":"integer","maximum":200.0,"minimum":1.0,"title":"Callers Limit","default":50},"callees_limit":{"type":"integer","maximum":200.0,"minimum":1.0,"title":"Callees Limit","default":50},"returns_limit":{"type":"integer","maximum":100.0,"minimum":1.0,"title":"Returns Limit","default":25},"commits_limit":{"type":"integer","maximum":50.0,"minimum":1.0,"title":"Commits Limit","default":10}},"type":"object","title":"SymbolContextRequest","description":"Body for ``POST /ontology/symbol-context``.\n\nEither ``node_id`` (preferred) or ``(name, type)`` resolves the\ntarget. When both are supplied ``node_id`` wins; when neither is\nsupplied the route 400s. The ``(name, type)`` resolver returns\n409 with the candidate list when the name + type combination\nmatches more than one live node so the caller picks unambiguously\non the next request."},"SymbolContextResponse":{"properties":{"target":{"$ref":"#/components/schemas/NodeResponse"},"containing_class":{"anyOf":[{"$ref":"#/components/schemas/NodeResponse"},{"type":"null"}]},"siblings":{"items":{"$ref":"#/components/schemas/NodeResponse"},"type":"array","title":"Siblings"},"tests":{"items":{"$ref":"#/components/schemas/NodeResponse"},"type":"array","title":"Tests"},"callers":{"items":{"$ref":"#/components/schemas/NodeResponse"},"type":"array","title":"Callers"},"callees":{"items":{"$ref":"#/components/schemas/NodeResponse"},"type":"array","title":"Callees"},"semantic_returns":{"items":{"$ref":"#/components/schemas/NodeResponse"},"type":"array","title":"Semantic Returns"},"recent_commits":{"items":{"$ref":"#/components/schemas/CommitTouchResponse"},"type":"array","title":"Recent Commits"}},"type":"object","required":["target"],"title":"SymbolContextResponse","description":"Public projection of :class:`SymbolContext`."},"TestPingResponse":{"properties":{"delivery_id":{"type":"string","format":"uuid","title":"Delivery Id"},"queued":{"type":"boolean","title":"Queued"}},"type":"object","required":["delivery_id","queued"],"title":"TestPingResponse","description":"Body for ``POST /v1/webhooks/{id}/test`` response."},"UpdateSlugRequest":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Name"},"trigger_kind":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Trigger Kind"},"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Description"},"filter_json":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Filter Json"}},"type":"object","title":"UpdateSlugRequest","description":"Body for ``PATCH /v1/events/slugs/{id}``."},"UpdateWebhookRequest":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Name"},"url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Url"},"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Description"},"event_filter":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Event Filter"},"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled","description":"Toggle ``status`` between ``active`` and ``disabled``. ``auto_disabled`` endpoints flip back to ``active`` when this is set to True."}},"type":"object","title":"UpdateWebhookRequest","description":"Body for ``PATCH /v1/webhooks/{id}``. All fields optional."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VolumeBucket":{"properties":{"ts":{"type":"string","format":"date-time","title":"Ts"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["ts","count"],"title":"VolumeBucket","description":"One time-bucketed event count."},"WebhookDeliveryPublic":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"endpoint_id":{"type":"string","format":"uuid","title":"Endpoint Id"},"event_id":{"type":"string","format":"uuid","title":"Event Id"},"event_kind":{"type":"string","title":"Event Kind"},"event_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Event Slug"},"attempt":{"type":"integer","title":"Attempt"},"status":{"type":"string","title":"Status"},"http_status":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Http Status"},"response_excerpt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Excerpt"},"error_class":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Class"},"next_retry_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Retry At"},"delivered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Delivered At"},"finalized_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Finalized At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","endpoint_id","event_id","event_kind","event_slug","attempt","status","http_status","response_excerpt","error_class","next_retry_at","delivered_at","finalized_at","created_at"],"title":"WebhookDeliveryPublic","description":"Public projection of one delivery attempt row."},"WebhookEndpointCreated":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"name":{"type":"string","title":"Name"},"url":{"type":"string","title":"Url"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"event_filter":{"additionalProperties":true,"type":"object","title":"Event Filter"},"status":{"type":"string","title":"Status"},"last_success_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Success At"},"last_failure_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Failure At"},"consecutive_failures":{"type":"integer","title":"Consecutive Failures"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"secret":{"type":"string","title":"Secret","description":"Raw signing secret. Returned exactly once at create / rotate time — never shown again."}},"type":"object","required":["id","workspace_id","name","url","description","event_filter","status","last_success_at","last_failure_at","consecutive_failures","created_at","updated_at","secret"],"title":"WebhookEndpointCreated","description":":class:`WebhookEndpointPublic` plus the raw signing secret.\n\nReturned ONLY by create + rotate-secret. The raw secret is never\npersisted; rotation re-mints both halves."},"WebhookEndpointPublic":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"name":{"type":"string","title":"Name"},"url":{"type":"string","title":"Url"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"event_filter":{"additionalProperties":true,"type":"object","title":"Event Filter"},"status":{"type":"string","title":"Status"},"last_success_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Success At"},"last_failure_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Failure At"},"consecutive_failures":{"type":"integer","title":"Consecutive Failures"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","workspace_id","name","url","description","event_filter","status","last_success_at","last_failure_at","consecutive_failures","created_at","updated_at"],"title":"WebhookEndpointPublic","description":"Public projection of a webhook endpoint row."},"WebhookSubscriberRow":{"properties":{"kind":{"type":"string","title":"Kind","default":"webhook"},"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"url":{"type":"string","title":"Url"},"status":{"type":"string","title":"Status"},"last_success_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Success At"},"last_failure_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Failure At"},"consecutive_failures":{"type":"integer","title":"Consecutive Failures"}},"type":"object","required":["id","name","url","status","last_success_at","last_failure_at","consecutive_failures"],"title":"WebhookSubscriberRow","description":"Webhook endpoint subscribed to a slug."},"WeightPatch":{"properties":{"operator_weight":{"type":"number","maximum":1.0,"minimum":-1.0,"title":"Operator Weight"},"reason":{"type":"string","maxLength":500,"minLength":1,"title":"Reason"}},"type":"object","required":["operator_weight","reason"],"title":"WeightPatch","description":"Body for PATCH /items/{memory_id}/weight.\n\nAttributes:\n    operator_weight: Float in [-1.0, +1.0].\n    reason: Non-empty audit note (1-500 chars)."},"WeightResponse":{"properties":{"memory_id":{"type":"string","format":"uuid","title":"Memory Id"},"operator_weight":{"type":"number","title":"Operator Weight"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["memory_id","operator_weight","reason"],"title":"WeightResponse","description":"Response after updating an operator weight.\n\nAttributes:\n    memory_id: Target memory UUID.\n    operator_weight: Persisted weight value.\n    reason: Audit note."},"WorkspaceTypeRow":{"properties":{"name":{"type":"string","title":"Name"},"category":{"type":"string","title":"Category"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["name","category","count"],"title":"WorkspaceTypeRow","description":"One workspace-known ontology type for the type picker."},"_CommitBrief":{"properties":{"commit":{"additionalProperties":true,"type":"object","title":"Commit"},"action":{"type":"string","title":"Action","default":"modified"},"author":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Author"},"diff_excerpt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Diff Excerpt"}},"type":"object","title":"_CommitBrief","description":"One touched-commit row in the symbol-context bundle."},"_EdgeProjection":{"properties":{"id":{"type":"string","title":"Id","description":"Edge UUID as string."},"type":{"type":"string","title":"Type","description":"Edge type tag."},"source_node_id":{"type":"string","title":"Source Node Id","description":"Source node UUID."},"target_node_id":{"type":"string","title":"Target Node Id","description":"Target node UUID."}},"type":"object","required":["id","type","source_node_id","target_node_id"],"title":"_EdgeProjection","description":"One edge in the family tree result."},"_NodeProjection":{"properties":{"id":{"type":"string","title":"Id","description":"Node UUID as string."},"type":{"type":"string","title":"Type","description":"Node type tag."},"name":{"type":"string","title":"Name","description":"Node display name."},"properties":{"additionalProperties":true,"type":"object","title":"Properties"}},"type":"object","required":["id","type","name"],"title":"_NodeProjection","description":"One node in the family tree result."},"_SymbolBrief":{"properties":{"id":{"type":"string","title":"Id","description":"Node UUID as string."},"name":{"type":"string","title":"Name","description":"Symbol display name."},"kind":{"type":"string","title":"Kind","default":"symbol"}},"type":"object","required":["id","name"],"title":"_SymbolBrief","description":"Symbol projection for the impact_of envelope."},"oxagen__capabilities__handlers__ontology_explain_function___FunctionBrief":{"properties":{"id":{"type":"string","title":"Id","description":"Node UUID as string."},"name":{"type":"string","title":"Name","description":"Function display name."},"signature":{"type":"string","title":"Signature","default":""},"file":{"type":"string","title":"File","default":""},"is_exported":{"type":"boolean","title":"Is Exported","default":false},"is_async":{"type":"boolean","title":"Is Async","default":false},"kind":{"type":"string","title":"Kind","default":"function"}},"type":"object","required":["id","name"],"title":"_FunctionBrief","description":"Seven-field function projection for the cookbook envelope."},"oxagen__capabilities__handlers__ontology_explain_function___NodeBrief":{"properties":{"id":{"type":"string","title":"Id","description":"Node UUID as string."},"name":{"type":"string","title":"Name","description":"Node display name."}},"type":"object","required":["id","name"],"title":"_NodeBrief","description":"Slim node projection — id + name."},"oxagen__capabilities__handlers__ontology_impact_of___NodeBrief":{"properties":{"id":{"type":"string","title":"Id","description":"Node UUID as string."},"name":{"type":"string","title":"Name","description":"Node display name."}},"type":"object","required":["id","name"],"title":"_NodeBrief","description":"Slim node projection — id + name."},"oxagen__capabilities__handlers__ontology_symbol_context___FunctionBrief":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"signature":{"type":"string","title":"Signature","default":""},"file":{"type":"string","title":"File","default":""},"is_exported":{"type":"boolean","title":"Is Exported","default":false},"is_async":{"type":"boolean","title":"Is Async","default":false},"kind":{"type":"string","title":"Kind","default":"function"}},"type":"object","required":["id","name"],"title":"_FunctionBrief","description":"Seven-field function projection for the target node."},"oxagen__capabilities__handlers__ontology_symbol_context___NodeBrief":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"}},"type":"object","required":["id","name"],"title":"_NodeBrief","description":"Slim node projection — id + name."}}}}