{
  "openapi": "3.1.0",
  "info": {
    "title": "Jymni Agent Ethics API",
    "version": "1.3.0",
    "description": "Reflective, actionable ethical counsel for proposed AI-agent actions. A response is advisory and never authorization to act.",
    "termsOfService": "https://www.jymni.com/agents/terms.html"
  },
  "servers": [{"url": "https://www.jymni.com"}],
  "paths": {
    "/api/v1/agent-enrollments": {
      "post": {
        "operationId": "startAgentEnrollment",
        "summary": "Request a human-owned agent identity",
        "description": "Starts a short-lived device authorization flow. This endpoint grants no authority. Show verification_uri_complete to a human, who must sign in and approve the exact bot identity and scope.",
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AgentEnrollmentRequest"}}}
        },
        "responses": {
          "201": {"description": "Enrollment is awaiting human authorization", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AgentEnrollment"}}}},
          "400": {"$ref": "#/components/responses/BadRequest"},
          "429": {"$ref": "#/components/responses/RateLimited"},
          "500": {"$ref": "#/components/responses/ServerError"}
        }
      }
    },
    "/api/v1/agent-enrollments/token": {
      "post": {
        "operationId": "pollAgentEnrollment",
        "summary": "Poll or acknowledge an agent enrollment",
        "description": "Poll no faster than the returned interval. After human approval, decrypt the one-time credential envelope using the private half of the X25519 key submitted when enrollment started. After secure storage, call again with acknowledge true so Jymni erases the delivery ciphertext.",
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AgentEnrollmentTokenRequest"}}}
        },
        "responses": {
          "200": {"description": "Terminal state, approved encrypted credential, or acknowledgement", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AgentEnrollmentToken"}}}},
          "202": {"description": "Enrollment still awaits human authorization", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AgentEnrollmentToken"}}}},
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "429": {"$ref": "#/components/responses/RateLimited"},
          "500": {"$ref": "#/components/responses/ServerError"}
        }
      }
    },
    "/api/v1/agent/me": {
      "get": {
        "operationId": "getAgentIdentity",
        "summary": "Inspect the authenticated agent identity",
        "security": [{"bearerAuth": []}],
        "responses": {
          "200": {"description": "Current durable agent principal and its effective limits", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AgentIdentity"}}}},
          "401": {"$ref": "#/components/responses/Unauthorized"}
        }
      }
    },
    "/api/v1/ethics/consultations": {
      "post": {
        "operationId": "createEthicsConsultation",
        "summary": "Review a proposed agent action",
        "description": "Returns a Jymni classification, workflow disposition, safeguards, missing facts, and a full evaluation report. Identical evaluation inputs may reuse a response generated within the preceding hour. This endpoint does not execute or authorize the proposed action.",
        "security": [{"bearerAuth": []}],
        "parameters": [{
          "name": "Idempotency-Key",
          "in": "header",
          "required": true,
          "description": "A unique 12–96 character key for this action attempt. Reuse only when retrying the same consultation.",
          "schema": {"type": "string", "minLength": 12, "maxLength": 96, "pattern": "^[A-Za-z0-9._:-]+$"}
        }],
        "requestBody": {
          "required": true,
          "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ConsultationRequest"}}}
        },
        "responses": {
          "200": {"description": "Completed consultation or idempotent replay", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Consultation"}}}},
          "400": {"$ref": "#/components/responses/BadRequest"},
          "401": {"$ref": "#/components/responses/Unauthorized"},
          "402": {"$ref": "#/components/responses/PaymentRequired"},
          "409": {"$ref": "#/components/responses/Conflict"},
          "429": {"$ref": "#/components/responses/RateLimited"},
          "500": {"$ref": "#/components/responses/ServerError"},
          "503": {"$ref": "#/components/responses/ServerError"}
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {"type": "http", "scheme": "bearer", "bearerFormat": "Jymni agent credential"}
    },
    "schemas": {
      "AgentEnrollmentRequest": {
        "type": "object",
        "required": ["client_public_key", "platform", "external_agent_id", "agent_name"],
        "additionalProperties": false,
        "properties": {
          "client_public_key": {"type": "string", "description": "URL-safe base64 encoding of a 32-byte ephemeral X25519 public key."},
          "platform": {"type": "string", "maxLength": 48, "pattern": "^[a-z0-9._-]+$"},
          "external_agent_id": {"type": "string", "maxLength": 160, "description": "Stable bot ID on the requesting platform."},
          "agent_name": {"type": "string", "maxLength": 80},
          "description": {"type": "string", "maxLength": 500},
          "environment": {"type": "string", "default": "production", "enum": ["development", "test", "sandbox", "staging", "production"]}
        }
      },
      "AgentEnrollment": {
        "type": "object",
        "required": ["id", "device_code", "user_code", "status", "expires_at", "expires_in", "interval", "verification_uri", "verification_uri_complete"],
        "properties": {
          "id": {"type": "string", "pattern": "^aen_"},
          "device_code": {"type": "string", "pattern": "^jymni_enroll_"},
          "user_code": {"type": "string", "pattern": "^[A-Z2-9]{4}-[A-Z2-9]{4}$"},
          "status": {"type": "string", "const": "pending_authorization"},
          "expires_at": {"type": "string", "format": "date-time"},
          "expires_in": {"type": "integer", "minimum": 300},
          "interval": {"type": "integer", "minimum": 3},
          "verification_uri": {"type": "string", "format": "uri"},
          "verification_uri_complete": {"type": "string", "format": "uri"}
        }
      },
      "AgentEnrollmentTokenRequest": {
        "type": "object",
        "required": ["device_code"],
        "additionalProperties": false,
        "properties": {
          "device_code": {"type": "string", "pattern": "^jymni_enroll_"},
          "acknowledge": {"type": "boolean", "default": false}
        }
      },
      "AgentEnrollmentToken": {
        "type": "object",
        "required": ["id", "status"],
        "properties": {
          "id": {"type": "string", "pattern": "^aen_"},
          "status": {"type": "string", "enum": ["pending_authorization", "approved", "denied", "expired", "consumed"]},
          "interval": {"type": "integer", "minimum": 3},
          "credential": {"$ref": "#/components/schemas/EncryptedCredential"},
          "client": {"$ref": "#/components/schemas/AgentClient"}
        }
      },
      "EncryptedCredential": {
        "type": "object",
        "required": ["algorithm", "server_public_key", "nonce", "ciphertext"],
        "properties": {
          "algorithm": {"type": "string", "const": "X25519-HKDF-SHA256-AES256GCM"},
          "server_public_key": {"type": "string"},
          "nonce": {"type": "string"},
          "ciphertext": {"type": "string"}
        }
      },
      "AgentIdentity": {
        "type": "object",
        "required": ["object", "client"],
        "properties": {
          "object": {"type": "string", "const": "agent.client"},
          "client": {"$ref": "#/components/schemas/AgentClient"}
        }
      },
      "ConsultationRequest": {
        "type": "object",
        "required": ["proposed_action"],
        "additionalProperties": false,
        "properties": {
        "evaluation_framework": {"type": "string", "enum": ["secular", "christianity", "judaism", "islam", "hinduism", "buddhism"], "description": "Explicit evaluation framework requested by the operator. Omit to preserve workspace routing, with General ethics as the default. The secular identifier means General ethics. Religious evidence uses only editions audited as public domain with unrestricted reuse in the United States; consult discovery for coverage and limits."},
          "guidance_mode": {"type": "string", "enum": ["standard", "children", "teens"], "default": "standard", "description": "Audience and coaching style, independent of ethical framework and decision context."},
          "evaluation_context": {"type": "string", "enum": ["personal", "business", "community"], "default": "personal", "description": "The decision setting; applied independently of the framework. Business focuses organizational responsibilities. This is separate from the context object of agent execution facts."},
          "proposed_action": {"type": "string", "minLength": 1, "maxLength": 2400, "description": "The concrete action the agent is about to take or recommend."},
          "objective": {"type": "string", "maxLength": 700, "description": "The human or operational goal the action is intended to serve."},
          "actor": {
            "description": "The acting system and optionally its responsible operator.",
            "oneOf": [
              {"type": "string", "maxLength": 300},
              {"$ref": "#/components/schemas/Actor"}
            ]
          },
          "stakeholders": {"$ref": "#/components/schemas/TextList"},
          "known_facts": {"$ref": "#/components/schemas/TextList"},
          "uncertainties": {"$ref": "#/components/schemas/TextList"},
          "constraints": {"$ref": "#/components/schemas/TextList"},
          "options": {"$ref": "#/components/schemas/TextList"},
          "context": {"$ref": "#/components/schemas/Context"}
        }
      },
      "Actor": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "name": {"type": "string", "maxLength": 300},
          "type": {"type": "string", "maxLength": 300},
          "role": {"type": "string", "maxLength": 300},
          "operator": {"type": "string", "maxLength": 300}
        }
      },
      "TextList": {"type": "array", "maxItems": 12, "items": {"type": "string", "maxLength": 500}},
      "Context": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "authority": {"type": "string", "enum": ["explicit", "delegated", "unclear", "none"]},
          "reversibility": {"type": "string", "enum": ["easy", "limited", "hard", "irreversible", "unknown"]},
          "sensitivity": {"type": "string", "enum": ["ordinary", "personal", "confidential", "regulated", "unknown"]},
          "deployment_stage": {"type": "string", "enum": ["design", "testing", "pre_deployment", "live", "incident_response"]},
          "quadrant_focus": {"type": "string", "enum": ["aligned", "self_serving", "well_meant", "reckless"], "description": "Optional quadrant rule for Jymni to inspect especially closely. It does not change independent scoring or disable the other quadrant rules."},
          "domain": {"type": "string", "maxLength": 80}
        }
      },
      "Consultation": {
        "type": "object",
        "required": ["id", "object", "client", "classification", "disposition", "summary", "verdict", "recommended_actions", "red_lines", "missing_facts", "scores", "confidence", "human_oversight_expected", "human_approval_required", "advisory_notice", "rubric", "report"],
        "properties": {
        "evaluation_framework": {"type": "object", "properties": {"id": {"type": "string", "enum": ["secular", "christianity", "judaism", "islam", "hinduism", "buddhism"]}, "label": {"type": "string"}, "textual_scope": {"type": "string"}, "spec_id": {"type": ["integer", "null"]}, "spec_version": {"type": "string"}, "spec_hash": {"type": "string"}, "source_collection_version": {"type": ["string", "null"]}, "source_rights_policy": {"type": ["string", "null"]}, "source_reuse_policy": {"type": ["string", "null"]}, "rights_jurisdiction": {"type": ["string", "null"]}, "rights_audited_on": {"type": ["string", "null"], "format": "date"}}},
        "guidance_mode": {"type": "object", "properties": {"id": {"type": "string", "enum": ["standard", "children", "teens"]}, "label": {"type": "string"}, "version": {"type": "string"}}},
        "evaluation_context": {"type": "object", "properties": {"id": {"type": "string", "enum": ["personal", "business", "community"]}, "label": {"type": "string"}, "version": {"type": "string"}, "disclaimer": {"type": "string"}}},
        "scriptural_assessment": {"type": ["object", "null"], "description": "Null for General ethics evaluations in every guidance mode. Religious assessment plus reasoning and interpretive limits.", "properties": {"Status": {"type": "string", "enum": ["Supports", "Conflicts", "Conditional", "Disputed", "Insufficient evidence"]}, "Reasoning": {"type": "string"}, "Interpretive Limits": {"type": "string"}}},
        "citations": {"type": "array", "description": "Religious citations contain server-supplied verified excerpts, context, and edition-specific public-domain and reuse evidence; application is an interpretation.", "items": {"type": "object", "properties": {"Source ID": {"type": "string"}, "Title": {"type": "string"}, "Reference": {"type": "string"}, "Quote": {"type": "string"}, "URL": {"type": "string"}, "Translation": {"type": "string"}, "Source Type": {"type": "string"}, "Context": {"type": "string"}, "Supports": {"type": "string"}, "Application Type": {"type": "string"}, "Quote Verification": {"type": "string"}, "Verified On": {"type": "string"}, "License": {"type": "string", "const": "Public Domain"}, "Rights Jurisdiction": {"type": "string"}, "Rights Source": {"type": "string"}, "Reuse Rights": {"type": "string", "const": "Unrestricted"}, "Reuse Source": {"type": "string"}, "Rights Audited On": {"type": "string", "format": "date"}, "Source Text SHA256": {"type": "string"}}}},
          "id": {"type": "string", "pattern": "^ec_"},
          "object": {"type": "string", "const": "ethics.consultation"},
          "client": {"$ref": "#/components/schemas/AgentClient"},
          "classification": {"type": "string", "enum": ["Aligned", "Self-Serving", "Well-Meant", "Reckless", "Undetermined"]},
          "disposition": {"$ref": "#/components/schemas/Disposition"},
          "summary": {"type": "string"},
          "verdict": {"type": "string"},
          "recommended_actions": {"type": "array", "items": {"$ref": "#/components/schemas/RecommendedAction"}},
          "red_lines": {"type": "array", "items": {"type": "string"}},
          "missing_facts": {"type": "array", "items": {"type": "string"}},
          "risk_signals": {"type": "object", "additionalProperties": true},
          "scores": {"type": "object", "required": ["ethical_impact", "practical_wisdom"], "properties": {"ethical_impact": {"type": ["integer", "null"], "minimum": 0, "maximum": 100}, "practical_wisdom": {"type": ["integer", "null"], "minimum": 0, "maximum": 100}}, "description": "Secular scores; both are null for religious assessments. Use scriptural_assessment and citations for religious evaluations."},
          "confidence": {"type": "string", "enum": ["Low", "Medium", "High"]},
          "external_verification": {"type": "string", "enum": ["Not performed", "User sources reviewed", "Authoritative sources reviewed"]},
          "human_oversight_expected": {"type": "boolean", "const": true},
          "human_approval_required": {"type": "boolean"},
          "advisory_notice": {"type": "string"},
          "rubric": {"$ref": "#/components/schemas/Rubric"},
          "usage": {"type": "object", "additionalProperties": true},
          "report": {"type": "object", "additionalProperties": true},
          "history_id": {"type": ["integer", "null"]},
          "created_at": {"type": "string", "format": "date-time"},
          "cached": {"type": "boolean", "description": "True when the evaluation reused an identical response generated within the preceding hour."},
          "idempotent_replay": {"type": "boolean"}
        }
      },
      "AgentClient": {
        "type": "object",
        "required": ["id", "type", "name", "environment", "scopes"],
        "description": "The durable agent principal whose credential initiated this consultation.",
        "properties": {
          "id": {"type": "string", "pattern": "^agt_"},
          "type": {"type": "string", "const": "agent"},
          "name": {"type": "string"},
          "description": {"type": "string"},
          "platform": {"type": "string", "description": "Present on device-enrollment delivery; identifies the requesting platform."},
          "external_agent_id": {"type": "string", "description": "Present on device-enrollment delivery; the platform's stable bot ID."},
          "environment": {"type": "string", "enum": ["development", "test", "sandbox", "staging", "production"]},
          "owner_user_id": {"type": "integer", "minimum": 1},
          "workspace_id": {"type": ["integer", "null"]},
          "scopes": {"type": "array", "items": {"type": "string", "enum": ["ethics:consult"]}},
          "status": {"type": "string", "enum": ["active", "disabled", "revoked"]},
          "daily_limit": {"type": "integer", "minimum": 1},
          "daily_count": {"type": "integer", "minimum": 0}
        }
      },
      "Disposition": {"type": "string", "enum": ["continue_with_safeguards", "revise_plan", "gather_information", "request_human_review", "do_not_continue"]},
      "RecommendedAction": {
        "type": "object",
        "required": ["action", "owner", "required_before_action"],
        "properties": {
          "action": {"type": "string"},
          "owner": {"type": "string", "enum": ["agent_or_operator"]},
          "required_before_action": {"type": "boolean"}
        }
      },
      "Rubric": {
        "type": "object",
        "required": ["version", "schema_version", "quadrant_focus"],
        "properties": {
          "version": {"type": "string"},
          "schema_version": {"type": "string", "const": "agent-consultation-v1"},
          "quadrant_focus": {"type": "string", "enum": ["all", "aligned", "self_serving", "well_meant", "reckless"]}
        }
      },
      "Error": {
        "type": "object",
        "required": ["error", "request_id"],
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message", "retryable"],
            "properties": {
              "code": {"type": "string"},
              "message": {"type": "string"},
              "retryable": {"type": "boolean"}
            }
          },
          "request_id": {"type": "string"}
        }
      }
    },
    "responses": {
      "BadRequest": {"description": "Invalid case or idempotency key", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "Unauthorized": {"description": "Missing, invalid, disabled, or revoked credential", "headers": {"WWW-Authenticate": {"schema": {"type": "string"}}}, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "PaymentRequired": {"description": "The account or workspace has insufficient credits", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "Conflict": {"description": "A request with this idempotency key is still processing", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "RateLimited": {"description": "Credential or service limit reached", "headers": {"Retry-After": {"schema": {"type": "integer"}}}, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}},
      "ServerError": {"description": "Temporary server or provider failure", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}
    }
  }
}
