{
 "openapi": "3.1.0",
 "info": {
  "title": "Run Budget Guard",
  "version": "1.0.0",
  "description": "Spending caps for one AI agent run, shared by every sub-agent. Free watch-only mode tracks spend and drafts a weekly report of runs that went over; Pro enforces the cap with a clear STOP before the next model or tool call. $9 a month. Free 500/day; Pro $9/month: https://pay.instaloops.com/b/8x2fZh0Ped799P94Kr83C3w"
 },
 "servers": [
  {
   "url": "https://budget.cloudforbots.com"
  }
 ],
 "components": {
  "securitySchemes": {
   "bearer": {
    "type": "http",
    "scheme": "bearer"
   }
  }
 },
 "paths": {
  "/api/run/open_budget": {
   "post": {
    "operationId": "open_budget",
    "summary": "Open a hard budget for one agent run before it starts: max dollars, tokens, calls and/or wall-clock seconds",
    "description": "Open a hard budget for one agent run before it starts: max dollars, tokens, calls and/or wall-clock seconds. Returns a handle. Give the handle to every sub-agent; they all draw from the same ledger, so one runaway loop or fork cannot exceed the run cap.",
    "security": [
     {},
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "label": {
          "type": "string",
          "description": "What this run is for, e.g. \"nightly code cleanup\"."
         },
         "max_usd": {
          "type": "number",
          "description": "Dollar cap for the whole run (your own estimates per call)."
         },
         "max_tokens": {
          "type": "integer",
          "description": "Token cap (input + output) for the whole run."
         },
         "max_calls": {
          "type": "integer",
          "description": "Cap on model/tool calls for the whole run."
         },
         "max_seconds": {
          "type": "integer",
          "description": "Wall-clock cap in seconds from now."
         },
         "ttl_hours": {
          "type": "integer",
          "description": "Handle lifetime (free max 24, Pro max 168). Default 24."
         },
         "mode": {
          "type": "string",
          "enum": [
           "shadow",
           "enforce"
          ],
          "description": "shadow = watch only: track spend and flag where the cap WOULD have stopped the run, never block (free). enforce = return allowed=false at the cap (Pro). Default: enforce on Pro, shadow on free."
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Result with job, understood, outcome, usage",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "401": {
      "description": "bad_agent_key"
     },
     "429": {
      "description": "free_limit_reached (includes upgrade link)"
     }
    }
   }
  },
  "/api/run/reserve": {
   "post": {
    "operationId": "reserve",
    "summary": "Call BEFORE each model call, tool call or sub-agent spawn with your estimate",
    "description": "Call BEFORE each model call, tool call or sub-agent spawn with your estimate. Returns allowed=true and deducts it, or allowed=false with the limit that tripped. When allowed is false, stop, do not retry, and return your partial result to the user. Atomic, so parallel sub-agents cannot both slip under the cap.",
    "security": [
     {},
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "handle": {
          "type": "string",
          "description": "The budget handle from open_budget (looks like bg_<id>.<secret>). Pass it to every sub-agent so they all spend from the same budget."
         },
         "usd": {
          "type": "number",
          "description": "Estimated cost of the next call in USD."
         },
         "tokens": {
          "type": "integer",
          "description": "Estimated tokens of the next call."
         },
         "calls": {
          "type": "integer",
          "description": "Number of calls to reserve (default 1)."
         },
         "note": {
          "type": "string",
          "description": "Short note, e.g. \"web_search #12\"."
         }
        },
        "required": [
         "handle"
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Result with job, understood, outcome, usage",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "401": {
      "description": "bad_agent_key"
     },
     "429": {
      "description": "free_limit_reached (includes upgrade link)"
     }
    }
   }
  },
  "/api/run/record": {
   "post": {
    "operationId": "record",
    "summary": "After a call, report the actual usage minus what you reserved (positive if it cost more, negative to give back an overestimate)",
    "description": "After a call, report the actual usage minus what you reserved (positive if it cost more, negative to give back an overestimate). Keeps the ledger honest without blocking.",
    "security": [
     {},
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "handle": {
          "type": "string",
          "description": "The budget handle from open_budget (looks like bg_<id>.<secret>). Pass it to every sub-agent so they all spend from the same budget."
         },
         "usd": {
          "type": "number"
         },
         "tokens": {
          "type": "integer"
         },
         "note": {
          "type": "string"
         }
        },
        "required": [
         "handle"
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Result with job, understood, outcome, usage",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "401": {
      "description": "bad_agent_key"
     },
     "429": {
      "description": "free_limit_reached (includes upgrade link)"
     }
    }
   }
  },
  "/api/run/weekly_report": {
   "post": {
    "operationId": "weekly_report",
    "summary": "Draft a plain-English report of the last 7 days for your key (or IP): runs, spend, runs that went over their cap, and dollars spent after a cap would have stopped them",
    "description": "Draft a plain-English report of the last 7 days for your key (or IP): runs, spend, runs that went over their cap, and dollars spent after a cap would have stopped them. Read-only; sends nothing. Show it to your user.",
    "security": [
     {},
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {}
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Result with job, understood, outcome, usage",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "401": {
      "description": "bad_agent_key"
     },
     "429": {
      "description": "free_limit_reached (includes upgrade link)"
     }
    }
   }
  },
  "/api/run/budget_status": {
   "post": {
    "operationId": "budget_status",
    "summary": "See spend vs limits, remaining budget, whether the run is stopped and why, and the last 20 ledger events",
    "description": "See spend vs limits, remaining budget, whether the run is stopped and why, and the last 20 ledger events. Set close=true when the run finishes.",
    "security": [
     {},
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "handle": {
          "type": "string",
          "description": "The budget handle from open_budget (looks like bg_<id>.<secret>). Pass it to every sub-agent so they all spend from the same budget."
         },
         "close": {
          "type": "boolean"
         }
        },
        "required": [
         "handle"
        ]
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Result with job, understood, outcome, usage",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "401": {
      "description": "bad_agent_key"
     },
     "429": {
      "description": "free_limit_reached (includes upgrade link)"
     }
    }
   }
  },
  "/api/key": {
   "post": {
    "operationId": "get_free_key",
    "summary": "Get a free API key",
    "responses": {
     "200": {
      "description": "api_key"
     }
    }
   }
  }
 }
}