Skip to content

Commit 25c4e70

Browse files
os-zhuangCopilot
andcommitted
docs(ai): document actions-as-tools (api + flow dispatch)
- content/docs/guides/ai-capabilities.mdx: new "Actions as Tools (auto-exposed)" section between AI Agents and RAG Pipelines — what gets exposed, plugin wiring (apiActionBaseUrl / apiActionHeaders), type:'api' body assembly rules, diagnostics. - skills/objectstack-ai/SKILL.md: add "Auto-Exposed Actions" subsection under Tool Configuration so action authors don't hand-author tool defs for headless invocation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 13a4f38 commit 25c4e70

2 files changed

Lines changed: 76 additions & 4 deletions

File tree

content/docs/guides/ai-capabilities.mdx

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ Complete guide to leveraging AI agents, RAG pipelines, and intelligent automatio
1111

1212
1. [AI Architecture](#ai-architecture)
1313
2. [AI Agents](#ai-agents)
14-
3. [RAG Pipelines](#rag-pipelines)
15-
4. [Natural Language Queries](#natural-language-queries)
16-
5. [Predictive Analytics](#predictive-analytics)
17-
6. [Best Practices](#best-practices)
14+
3. [Actions as Tools (auto-exposed)](#actions-as-tools-auto-exposed)
15+
4. [RAG Pipelines](#rag-pipelines)
16+
5. [Natural Language Queries](#natural-language-queries)
17+
6. [Predictive Analytics](#predictive-analytics)
18+
7. [Best Practices](#best-practices)
1819

1920
---
2021

@@ -356,6 +357,56 @@ Use statistical analysis and ML.`,
356357

357358
---
358359

360+
## Actions as Tools (auto-exposed)
361+
362+
Every declarative {@link Action} you attach to an object is **automatically exposed as an AI tool**, named `action_<actionName>`. When the LLM picks one, the AI runtime dispatches to the same handler Studio's row toolbar would invoke — your business logic stays in one place.
363+
364+
### What gets exposed
365+
366+
The AI runtime walks every registered object's `actions[]` and exposes the ones that pass safety + wiring checks. Three action types are supported:
367+
368+
| `action.type` | Dispatch path | Wiring needed |
369+
|:---|:---|:---|
370+
| `script` | `IDataEngine.executeAction(object, target, ctx)` — the same call Studio makes | none beyond the metadata service |
371+
| `api` | HTTP call to `action.target` via `ApiActionClient` (default: `fetch`) | `apiBaseUrl` (or a custom `apiClient`) |
372+
| `flow` | `IAutomationService.execute(target, { triggerData })` | `automation` service registered |
373+
374+
Studio-only types (`url`, `modal`, `form`) and any action with `confirmText`, `mode: 'delete'`, or `variant: 'danger'` are skipped — those require Phase-3 HITL approval. Owners can also opt out per action with `aiExposed: false`.
375+
376+
### Wiring it up
377+
378+
```typescript
379+
import { AIServicePlugin } from '@objectstack/service-ai';
380+
381+
kernel.use(
382+
new AIServicePlugin({
383+
// Enables type:'api' action dispatch. Relative `target` paths
384+
// ('/api/v1/...') are resolved against this base URL.
385+
apiActionBaseUrl: process.env.OS_AI_ACTION_API_BASE_URL,
386+
// Forwarded on every api-action HTTP call (auth, environment id, ...).
387+
apiActionHeaders: { Authorization: `Bearer ${process.env.SERVICE_TOKEN}` },
388+
}),
389+
);
390+
```
391+
392+
If `automation` is already registered with the kernel, `type:'flow'` actions are picked up automatically — no extra wiring needed.
393+
394+
### `type:'api'` body assembly
395+
396+
For api actions, the request body is built from three sources (last wins):
397+
398+
1. **User-collected params** (the keys the LLM filled in).
399+
2. **`recordIdParam`** — when row-context, the id is placed flat at `action.recordIdParam`, using `recordIdField` (default `'id'`) to pick the value off the record.
400+
3. **`bodyExtra`** — constant fields that always override.
401+
402+
`bodyShape: { wrap: 'data' }` nests the user params under `data` while keeping `recordIdParam` flat — matching shapes like better-auth's `organization/update`.
403+
404+
### Diagnostics
405+
406+
`registerActionsAsTools()` returns `{ registered, skipped }`. Studio surfaces the skipped list with reasons (e.g. `"no apiClient or apiBaseUrl configured"`, `"mode='delete' — destructive"`) so action authors can see at a glance whether their action will be LLM-callable.
407+
408+
---
409+
359410
## RAG Pipelines
360411

361412
Retrieval-Augmented Generation (RAG) provides AI with access to your knowledge base.

skills/objectstack-ai/SKILL.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,27 @@ Tools are the atomic operations that skills expose to agents.
219219
}
220220
```
221221

222+
### Auto-Exposed Actions
223+
224+
You usually **don't author tool definitions by hand** for action invocation. Every `Action` you attach to an object via `defineObject({ actions: [...] })` is auto-exposed as a tool named `action_<actionName>` by `registerActionsAsTools()` (invoked from `AIServicePlugin`).
225+
226+
Three action types dispatch headlessly:
227+
228+
| `action.type` | Dispatch | Wiring |
229+
|:---|:---|:---|
230+
| `script` | `IDataEngine.executeAction(object, target, ctx)` — same as Studio's row toolbar | none |
231+
| `api` | HTTP call to `action.target` (`fetch`-based by default) | `AIServicePlugin({ apiActionBaseUrl, apiActionHeaders })` or custom `apiClient` |
232+
| `flow` | `IAutomationService.execute(target, { triggerData })` | `automation` service registered with the kernel |
233+
234+
**Skipped automatically:**
235+
- UI-only types (`url`, `modal`, `form`).
236+
- Dangerous variants (`confirmText` set, `mode: 'delete'`, `variant: 'danger'`) — Phase 3 HITL.
237+
- Owner opt-outs (`aiExposed: false`).
238+
239+
**`type:'api'` body assembly** (last wins): user params → `recordIdParam` (using `recordIdField`, default `'id'`) → `bodyExtra`. `bodyShape: { wrap: 'data' }` nests user params under `data` while keeping `recordIdParam` flat.
240+
241+
Use `actionSkipReason(action, ctx)` (exported from `@objectstack/service-ai`) when authoring an action and you want to know *why* it isn't surfacing in chat. Studio's "AI exposure" diagnostics use the same predicate.
242+
222243
---
223244

224245
## RAG Pipeline Configuration

0 commit comments

Comments
 (0)