Declaring actions
An action is a hook that declares an api_schema in abstra.json. Other projects can only call hooks that declare one, and the schema is what they see and are validated against.
{
"hooks": [
{
"id": "930efb6d-f985-4f80-89f6-3f9efa52a539",
"path": "quote-order",
"title": "Quote Order",
"file": "quote_order.py",
"api_schema": {
"description": "Prices an order. Computes a quote only; nothing is stored.",
"input": {
"type": "object",
"properties": {
"customer": {
"type": "object",
"properties": {
"name": { "type": "string" },
"email": { "type": "string" }
},
"required": ["name", "email"]
},
"items": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#/$defs/lineItem" }
}
},
"required": ["customer", "items"],
"additionalProperties": false,
"$defs": {
"lineItem": {
"type": "object",
"properties": {
"sku": { "type": "string", "pattern": "^[A-Z]{3}-[0-9]{3}$" },
"quantity": { "type": "integer", "minimum": 1 }
},
"required": ["sku", "quantity"]
}
}
},
"output": {
"type": "object",
"properties": { "total": { "type": "number" } }
}
}
}
]
}
| Field | Required | Description |
|---|---|---|
description | no | What the action does. Shown to callers and AI agents. |
input | yes | JSON Schema (2020-12) of the parameters, with "type": "object". Use $defs and "$ref": "#/$defs/..." for reusable parts. |
output | no | JSON Schema of what the hook answers. Shown to callers; not enforced. |
- The action's name comes from the hook's path (
quote-orderabove): characters other than letters, digits,-and_become_. - Parameters are validated before the hook runs. A call that doesn't match gets every error back, with its path, and the hook never runs.
"additionalProperties": falserejects parameters the hook doesn't expect, which catches typos early.- Changes to
api_schematake effect when you deploy.
Adding a schema
You can edit abstra.json directly, or ask Smart Chat to "add an api_schema to the Quote Order hook" with the parameters it takes.
Writing the hook
The parameters arrive as the request's JSON body:
import abstra.hooks as ah
order, query, headers = ah.get_request()
total = sum(item["quantity"] * price_of(item["sku"]) for item in order["items"])
ah.send_json({"total": total})
- Answer with
send_jsonfor structured results: callers get it parsed. - Answer with an error status (for example
ah.send_json({"error": "Unknown coupon"}, status_code=422)) to makerun_app_actionraiseAppActionErrorwith that status and your body indetails. - The same hook can still be called over HTTP at its URL. Those requests skip the schema validation, so keep validating what your code relies on.
Who can call it
Declaring a schema doesn't change who can run the hook:
- A public hook can be called by any project, as it can be called by anyone over HTTP.
- A private hook can be called by the projects holding one of its roles. See Giving a project access.