Files
attune/docs/api/api-actions.md
2026-02-04 17:46:30 -06:00

598 lines
14 KiB
Markdown

# Action Management API
This document describes the Action Management API endpoints for the Attune automation platform.
## Overview
Actions are the executable units in Attune that perform specific tasks. Each action belongs to a pack and can have parameters, output schemas, and runtime requirements.
**Base Path:** `/api/v1/actions`
## Data Model
### Action
```json
{
"id": 1,
"ref": "core.http.get",
"pack": 1,
"pack_ref": "core",
"label": "HTTP GET Request",
"description": "Performs an HTTP GET request to a specified URL",
"entrypoint": "/actions/http_get.py",
"runtime": 1,
"param_schema": {
"type": "object",
"properties": {
"url": { "type": "string" },
"headers": { "type": "object" }
},
"required": ["url"]
},
"out_schema": {
"type": "object",
"properties": {
"status_code": { "type": "integer" },
"body": { "type": "string" }
}
},
"created": "2024-01-13T10:00:00Z",
"updated": "2024-01-13T10:00:00Z"
}
```
### Action Summary (List View)
```json
{
"id": 1,
"ref": "core.http.get",
"pack_ref": "core",
"label": "HTTP GET Request",
"description": "Performs an HTTP GET request to a specified URL",
"entrypoint": "/actions/http_get.py",
"runtime": 1,
"created": "2024-01-13T10:00:00Z",
"updated": "2024-01-13T10:00:00Z"
}
```
## Endpoints
### List All Actions
Retrieve a paginated list of all actions.
**Endpoint:** `GET /api/v1/actions`
**Query Parameters:**
- `page` (integer, optional): Page number (default: 1)
- `per_page` (integer, optional): Items per page (default: 20, max: 100)
**Response:** `200 OK`
```json
{
"data": [
{
"id": 1,
"ref": "core.http.get",
"pack_ref": "core",
"label": "HTTP GET Request",
"description": "Performs an HTTP GET request",
"entrypoint": "/actions/http_get.py",
"runtime": 1,
"created": "2024-01-13T10:00:00Z",
"updated": "2024-01-13T10:00:00Z"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 1,
"total_pages": 1
}
}
```
---
### List Actions by Pack
Retrieve all actions belonging to a specific pack.
**Endpoint:** `GET /api/v1/packs/:pack_ref/actions`
**Path Parameters:**
- `pack_ref` (string): Pack reference identifier
**Query Parameters:**
- `page` (integer, optional): Page number (default: 1)
- `per_page` (integer, optional): Items per page (default: 20, max: 100)
**Response:** `200 OK`
```json
{
"data": [
{
"id": 1,
"ref": "core.http.get",
"pack_ref": "core",
"label": "HTTP GET Request",
"description": "Performs an HTTP GET request",
"entrypoint": "/actions/http_get.py",
"runtime": 1,
"created": "2024-01-13T10:00:00Z",
"updated": "2024-01-13T10:00:00Z"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 1,
"total_pages": 1
}
}
```
**Errors:**
- `404 Not Found`: Pack with the specified ref does not exist
---
### Get Action by Reference
Retrieve a single action by its reference identifier.
**Endpoint:** `GET /api/v1/actions/:ref`
**Path Parameters:**
- `ref` (string): Action reference identifier (e.g., "core.http.get")
**Response:** `200 OK`
```json
{
"data": {
"id": 1,
"ref": "core.http.get",
"pack": 1,
"pack_ref": "core",
"label": "HTTP GET Request",
"description": "Performs an HTTP GET request to a specified URL",
"entrypoint": "/actions/http_get.py",
"runtime": 1,
"param_schema": { ... },
"out_schema": { ... },
"created": "2024-01-13T10:00:00Z",
"updated": "2024-01-13T10:00:00Z"
}
}
```
**Errors:**
- `404 Not Found`: Action with the specified ref does not exist
---
### Create Action
Create a new action in the system.
**Endpoint:** `POST /api/v1/actions`
**Request Body:**
```json
{
"ref": "core.http.get",
"pack_ref": "core",
"label": "HTTP GET Request",
"description": "Performs an HTTP GET request to a specified URL",
"entrypoint": "/actions/http_get.py",
"runtime": 1,
"param_schema": {
"type": "object",
"properties": {
"url": { "type": "string" },
"headers": { "type": "object" }
},
"required": ["url"]
},
"out_schema": {
"type": "object",
"properties": {
"status_code": { "type": "integer" },
"body": { "type": "string" }
}
}
}
```
**Required Fields:**
- `ref`: Unique reference identifier (alphanumeric, dots, underscores, hyphens)
- `pack_ref`: Reference to the parent pack
- `label`: Human-readable name (1-255 characters)
- `description`: Action description (min 1 character)
- `entrypoint`: Execution entry point (1-1024 characters)
**Optional Fields:**
- `runtime`: Runtime ID for execution environment
- `param_schema`: JSON Schema defining input parameters
- `out_schema`: JSON Schema defining expected outputs
**Response:** `201 Created`
```json
{
"data": {
"id": 1,
"ref": "core.http.get",
"pack": 1,
"pack_ref": "core",
"label": "HTTP GET Request",
"description": "Performs an HTTP GET request to a specified URL",
"entrypoint": "/actions/http_get.py",
"runtime": 1,
"param_schema": { ... },
"out_schema": { ... },
"created": "2024-01-13T10:00:00Z",
"updated": "2024-01-13T10:00:00Z"
},
"message": "Action created successfully"
}
```
**Errors:**
- `400 Bad Request`: Invalid request data or validation failure
- `404 Not Found`: Referenced pack does not exist
- `409 Conflict`: Action with the same ref already exists
---
### Update Action
Update an existing action's properties.
**Endpoint:** `PUT /api/v1/actions/:ref`
**Path Parameters:**
- `ref` (string): Action reference identifier
**Request Body:**
All fields are optional. Only provided fields will be updated.
```json
{
"label": "Updated HTTP GET Request",
"description": "Updated description",
"entrypoint": "/actions/http_get_v2.py",
"runtime": 2,
"param_schema": { ... },
"out_schema": { ... }
}
```
**Response:** `200 OK`
```json
{
"data": {
"id": 1,
"ref": "core.http.get",
"pack": 1,
"pack_ref": "core",
"label": "Updated HTTP GET Request",
"description": "Updated description",
"entrypoint": "/actions/http_get_v2.py",
"runtime": 2,
"param_schema": { ... },
"out_schema": { ... },
"created": "2024-01-13T10:00:00Z",
"updated": "2024-01-13T12:00:00Z"
},
"message": "Action updated successfully"
}
```
**Errors:**
- `400 Bad Request`: Invalid request data or validation failure
- `404 Not Found`: Action with the specified ref does not exist
---
### Delete Action
Delete an action from the system.
**Endpoint:** `DELETE /api/v1/actions/:ref`
**Path Parameters:**
- `ref` (string): Action reference identifier
**Response:** `200 OK`
```json
{
"success": true,
"message": "Action 'core.http.get' deleted successfully"
}
```
**Errors:**
- `404 Not Found`: Action with the specified ref does not exist
---
### Get Queue Statistics
Retrieve real-time queue statistics for an action's execution queue.
**Endpoint:** `GET /api/v1/actions/:ref/queue-stats`
**Path Parameters:**
- `ref` (string): Action reference identifier
**Response:** `200 OK`
```json
{
"data": {
"action_id": 1,
"action_ref": "core.http.get",
"queue_length": 5,
"active_count": 2,
"max_concurrent": 3,
"oldest_enqueued_at": "2025-01-27T10:30:00Z",
"total_enqueued": 1250,
"total_completed": 1245,
"last_updated": "2025-01-27T12:45:30Z"
}
}
```
**Response Fields:**
- `action_id`: Numeric action ID
- `action_ref`: Action reference identifier
- `queue_length`: Number of executions waiting in queue
- `active_count`: Number of currently running executions
- `max_concurrent`: Maximum concurrent executions allowed (from policy)
- `oldest_enqueued_at`: Timestamp of oldest queued execution (null if queue empty)
- `total_enqueued`: Lifetime count of executions enqueued
- `total_completed`: Lifetime count of executions completed
- `last_updated`: Last time statistics were updated
**Response When No Queue Stats Available:** `200 OK`
```json
{
"data": {
"action_id": 1,
"action_ref": "core.http.get",
"queue_length": 0,
"active_count": 0,
"max_concurrent": null,
"oldest_enqueued_at": null,
"total_enqueued": 0,
"total_completed": 0,
"last_updated": null
}
}
```
**Errors:**
- `404 Not Found`: Action with the specified ref does not exist
**Use Cases:**
- Monitor action execution queue depth
- Detect stuck or growing queues
- Track execution throughput
- Validate policy enforcement
- Operational dashboards
**Related Documentation:**
- [Queue Architecture](./queue-architecture.md)
- [Policy Enforcement](./executor-service.md#policy-enforcement)
---
## Examples
### Creating a Simple Action
```bash
curl -X POST http://localhost:3000/api/v1/actions \
-H "Content-Type: application/json" \
-d '{
"ref": "mypack.hello_world",
"pack_ref": "mypack",
"label": "Hello World",
"description": "Prints hello world",
"entrypoint": "/actions/hello.py"
}'
```
### Creating an Action with Parameter Schema
```bash
curl -X POST http://localhost:3000/api/v1/actions \
-H "Content-Type: application/json" \
-d '{
"ref": "mypack.send_email",
"pack_ref": "mypack",
"label": "Send Email",
"description": "Sends an email message",
"entrypoint": "/actions/send_email.py",
"param_schema": {
"type": "object",
"properties": {
"to": { "type": "string", "format": "email" },
"subject": { "type": "string" },
"body": { "type": "string" }
},
"required": ["to", "subject", "body"]
}
}'
```
### Listing Actions for a Pack
```bash
curl http://localhost:3000/api/v1/packs/core/actions
```
### Updating an Action
```bash
curl -X PUT http://localhost:3000/api/v1/actions/mypack.hello_world \
-H "Content-Type: application/json" \
-d '{
"label": "Hello World v2",
"description": "Updated hello world action"
}'
```
### Deleting an Action
```bash
curl -X DELETE http://localhost:3000/api/v1/actions/mypack.hello_world
```
### Getting Queue Statistics
```bash
curl http://localhost:3000/api/v1/actions/core.http.get/queue-stats
```
**Example Response:**
```json
{
"data": {
"action_id": 1,
"action_ref": "core.http.get",
"queue_length": 12,
"active_count": 5,
"max_concurrent": 5,
"oldest_enqueued_at": "2025-01-27T12:40:00Z",
"total_enqueued": 523,
"total_completed": 511,
"last_updated": "2025-01-27T12:45:30Z"
}
}
```
---
## Validation Rules
### Action Reference (`ref`)
- Must be unique across all actions
- Can contain alphanumeric characters, dots (.), underscores (_), and hyphens (-)
- Typically follows the pattern: `pack_name.action_name`
- Example: `core.http.get`, `aws.ec2.start_instance`
### Pack Reference (`pack_ref`)
- Must reference an existing pack
- The pack must exist before creating actions for it
### Entry Point (`entrypoint`)
- Path or identifier for the executable code
- Can be a file path, module name, function name, etc.
- Format depends on the runtime environment
### Schemas (`param_schema`, `out_schema`)
- Must be valid JSON Schema documents
- Used for validation during action execution
- Helps with auto-generating documentation and UI
---
## Best Practices
1. **Naming Conventions**
- Use descriptive, hierarchical names: `pack.category.action`
- Keep names concise but meaningful
- Use lowercase with dots as separators
2. **Schema Definitions**
- Always provide `param_schema` for clarity
- Define `required` fields in schemas
- Use appropriate JSON Schema types and formats
- Document schema fields with descriptions
3. **Entry Points**
- Use consistent paths relative to the pack root
- Keep entry points simple and maintainable
- Consider versioning: `/actions/v1/http_get.py`
4. **Runtime Association**
- Specify runtime when actions have specific dependencies
- Null runtime means use default/generic runtime
- Ensure runtime exists before creating action
5. **Error Handling**
- Design actions to handle errors gracefully
- Use output schemas to define error structures
- Log execution details for debugging
6. **Queue Monitoring**
- Use `/queue-stats` endpoint to monitor execution queues
- Alert on high `queue_length` (> 100)
- Investigate when `oldest_enqueued_at` is old (> 30 minutes)
- Track completion rate: `total_completed / total_enqueued`
---
## Queue Statistics
The `/queue-stats` endpoint provides real-time visibility into action execution queues.
### Understanding Queue Metrics
- **queue_length**: Executions waiting to run (0 = healthy)
- **active_count**: Executions currently running
- **max_concurrent**: Policy-enforced concurrency limit
- **oldest_enqueued_at**: How long the oldest execution has been waiting
- **total_enqueued/completed**: Lifetime throughput metrics
### Healthy vs Unhealthy Queues
**Healthy:**
-`queue_length` is 0 or low (< 10)
-`active_count``max_concurrent` during load
-`oldest_enqueued_at` is recent (< 5 minutes)
-`total_completed` increases steadily
**Unhealthy:**
- ⚠️ `queue_length` consistently high (> 50)
- ⚠️ `oldest_enqueued_at` is old (> 30 minutes)
- 🚨 Queue not progressing (stats not updating)
- 🚨 `active_count` < `max_concurrent` (workers stuck)
### Monitoring Recommendations
1. **Set up alerts** for high queue depths
2. **Track trends** in `total_enqueued` vs `total_completed`
3. **Investigate spikes** in `queue_length`
4. **Scale workers** when queues consistently fill
5. **Adjust policies** if concurrency limits are too restrictive
For detailed queue architecture and troubleshooting, see [Queue Architecture Documentation](./queue-architecture.md).
---
## Related Documentation
- [Pack Management API](./api-packs.md)
- [Runtime Management API](./api-runtimes.md)
- [Rule Management API](./api-rules.md)
- [Execution API](./api-executions.md)
- [Queue Architecture](./queue-architecture.md)
- [Executor Service](./executor-service.md)
---
**Last Updated:** January 27, 2025