Simulator.Company actor (record) specialist. Use when the user wants to create, update, read, search, or filter the *instances* of a form template (a.k.a. Account Template records) — i.e. data-bearing actors — and needs the `data` value protocol right. Activate when the user says "create an actor", "add a record", "create a record from this template", "fill in a form", "update actor data", "find actors where field = …", "filter actors by balance", "создай актор", "заполни шаблон", or "добавь ...
Scanned 9/5/2026
Install to Claude Code
npx -y skills add corezoid/simulator-ai-plugin --skill simulator-actors --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Simulator Actors?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/corezoid-simulator-actors)More formats (shields.io, HTML) on the badges page.
---
name: simulator-actors
description: >
Simulator.Company actor (record) specialist. Use when the user wants to create,
update, read, search, or filter the *instances* of a form template (a.k.a.
Account Template records) — i.e. data-bearing actors — and needs the `data`
value protocol right. Activate when the user says "create an actor", "add a
record", "create a record from this template", "fill in a form", "update actor
data", "find actors where field = …", "filter actors by balance", "создай актор",
"заполни шаблон", or "добавь запись". ALSO use this skill when the user asks what
**processes / functions / Corezoid processes** an actor has or can call, or about an
actor's **shared API keys / available functions** — call `getCorezoidProcesses`:
"what processes/functions can this actor call", "actor's connected processes",
"actor's API keys", "available functions of the actor", "які процеси/функції доступні
актору", "процеси актора", "функції актора", "ключі доступу актора", "какие
процессы/функции у актора", "процессы актора", "доступные функции актора". For
graph/flowchart STRUCTURE (links, layers, FlowchartBlock diagrams) use `simulator-graph`;
for designing the template itself use `simulator-forms`.
---
> **Curated tool names (v2 server):** `createActor`, `getActor`, `getActorByRef`,
> `updateActor`, `setActorStatus`, `deleteActor`, `searchActors`, `filterActors`,
> `searchLayerActors`, `getSystemActor`, `getCorezoidProcesses`. Call them by these exact names.
>
> **`getCorezoidProcesses(actorId)`** is THE tool for any question about an actor's
> **processes / functions / available API integrations** — it returns the Corezoid processes
> shared to the actor via its access API keys (what that actor can call). If the user asks
> "what functions/processes does this actor have", "what can this actor call", or about the
> actor's shared API keys, call `getCorezoidProcesses` — do not guess or use a graph-traversal tool.
>
> **`getSystemActor`** resolves the system "twin" actor of a workspace entity — pass
> `objType="user"`, `objId="<userId>"` to get the actor representing a user (so you can attach
> accounts to it or move value between users). Find the `userId` first with `searchUsers` /
> `getUsers`. Money movement between users then goes through their twin actors' accounts via
> **transfers** — see `simulator-finance`.
# Simulator.Company Actor (Record) Specialist
You create and manage **actors** — the *instances* of a form template (Account
Template). An actor's field values live in its `data` object. Getting the `data`
shape right is the whole job, so this skill exists to make that mechanical.
> **Relationship to the other skills**
> - **`simulator-forms`** designs the *template* (`sections`/fields). Read it / a form
> first to learn the field `id`s.
> - **`simulator-actors`** (this skill) creates/edits the *records* of that template.
> - **`simulator-graph`** handles graph *structure* — links, layers, FlowchartBlock
> diagrams. If the user wants to wire actors together or place them on a layer, defer there.
> - **`simulator-finance`** handles accounts/transactions on actors.
## Workspace Context Check (MANDATORY FIRST STEP)
Verify `accId` is known before any tool call. If not provided, ask:
> Ask the user — **in their own language** (English, Ukrainian, or Russian) — which workspace to work in, i.e. for the Workspace ID (`accId`).
`createActor` can also resolve a `formName` to its id, but only with a workspace set.
---
## The golden rule: `data` is keyed by field `id`
An actor's `data` is keyed by each form field's **`id`** (`item_<digits>`) — **not** by
the field `title` and **not** by its secondary `key`. So the first step of *every* actor
create/update is:
1. **Resolve the form.** `getForm(formId)` (or `searchForms` then `getForm`). Pass
`filter="id,title,sections"` to keep it small.
2. **Map each field you want to set** → its `id` and `class`.
3. **Build `data`** using the per-class value shapes below.
### Value shape by field class
| Form field class / source | Value in `data` |
|---|---|
| `edit` text / password / email / phone | string — `"dsdf@fsdf.com"` |
| `edit` int / float | number — `1` |
| `check` | boolean — `true` |
| `radio` | the selected option's `value` (string) — `"o2"` |
| `select` (static `options`) | array of chosen option object(s) — `[{"color":"#863434","title":"one","value":"s1"}]` |
| `select` → `layer`/`actorFilter`/`actorsBag`/`actors`/`formFilter` | `[{"type":"actor","title":…,"value":"<actor UUID>"}]` (formFilter = the actors of a given form) |
| `select` → `forms` | `[{"type":"form","title":…,"value":<form id number>}]` |
| `select` → `currencies` | `[{"type":"currency","title":…,"value":<currency id number>}]` |
| `select` → `accountNames` | `[{"type":"accountName","title":…,"value":"<account-name UUID>"}]` |
| `select` → `workspaceMembers` | `[{"type":"workspaceMembers","title":…,"value":<user id number>}]` |
| `select` → `api`/`corezoidSyncApi` | array of synced options (`[]` until synced) |
| `multiSelect` | array — `[{"title":"one","value":"…"},{"title":"two","value":"…"}]` |
| `calendar` | `{"startDate":…,"endDate":…,"timeZoneOffset":-180,"sendInvite":false}` (unix **seconds**) |
| `upload` | array of file refs (`[]` when empty) |
| `label` / `button` / `image` | **no entry** — display-only |
> The `type` discriminator only appears on **dynamic** `select` values. Static
> `select`/`multiSelect` values carry just `{title,value,color?}`. For a dynamic
> `select`, the `value` must be a real referenced id (actor UUID / currency id /
> account-name UUID / user id) — resolve it first (e.g. `getCurrencies`,
> `getAccountNames`, `searchActors`) rather than guessing.
> **Geolocation (top-level, not `data`).** An actor carries an optional position independent
> of its form fields: `geoPosition` — `{"lat": <number>, "lon": <number>}` in WGS84 decimal
> degrees, or `null` to clear — and `geoName` — a location name string, or `null`. Both are set
> on `createActor`/`updateActor`. Latitude is hard-bounded to -90..90 (out of range is rejected),
> longitude outside ±180 wraps cyclically, and coordinates round to 6 decimals; `lat`/`lon` are
> set as a pair.
Full reference: `$CLAUDE_PLUGIN_ROOT/docs/entities/actors.md` and `…/forms.md`.
### Multiform actors (`__form__<formId>:<itemId>`)
An actor can instantiate **several forms at once** (a *multiform* actor; the linked form
tree is called a **UAT**). Its `data` then carries fields from more than one form, namespaced
by a key prefix:
- Fields of the actor's **root** `formId` (the one you pass to `createActor`/`updateActor`) →
the **plain** field `id`, e.g. `"name"`.
- Fields owned by **another** form → **`__form__<thatFormId>:<itemId>`**.
```json
// data for an actor created under its root form, with one field from form 16951
{
"name": "Kulo Oleksandr",
"__form__16951:position": "Software engineer"
}
```
The prefix changes only the **key** — the value still follows the per-class shapes above.
Notes:
- To learn `<thatFormId>`'s field ids, `getForm(<thatFormId>)` just like the root form.
- **Discover the tree** with `getFormsTree(accId, formId)` / `getLinkedForms(typeLink, formId)`
(see `simulator-forms`) to find which forms a multiform actor spans before writing its `data`.
- Attaching the *set* of forms to an actor (`PUT /actors/actor_forms`) is still **not** a curated
tool — but you can already write/read multiform `data` via `createActor`/`updateActor`/`getActor`.
#### Creating under the tree when asked for a CHILD (leaf) form
In a UAT workspace, an actor can only be created under the **root** form of the tree — not
under an arbitrary leaf. So when the user says *"create an actor for form X"* and
`getForm(X)` returns a **non-empty `parentId`** (X is a nested/child form), do **not** call
`createActor(formId=X, …)` — the backend rejects it with **`400: Form <id> is not UAT`**.
Instead:
1. **Walk up `parentId`** from X to the root form of the UAT tree (`getForm` repeatedly until
`parentId` is empty).
2. **Call `createActor` with `formId` = the root.**
3. Put the **root's own fields** under their plain id (`"name"`), and the **requested child
form's fields** under the `__form__<childFormId>:<itemId>` prefix.
```json
// Request: "create an actor for form Employee (16951)", where Employee.parentId = People (16950)
// → create under the ROOT People (16950), not under Employee:
createActor(formId=16950, title="Olena Kovalenko", data={
"name": "Olena Kovalenko", // People (root) field
"__form__16951:position": "Senior Backend Engineer" // Employee (child) field
})
```
> **Do NOT** flip the child form to `uat` status via `setFormStatus` to "work around" the
> error — that mutates the shared template for everyone. Use the **root** form as the
> `formId` instead.
---
## Create an actor
```
createActor(
formId=42, # or formName="Car" (resolved via the workspace)
title="Toyota Camry 2023",
color="#409547", # optional
ref="car-toyota-camry-2023", # optional, unique per form
contextLayerId="<layer UUID>", # optional — place it on a layer
data={
"item_make": "Toyota",
"item_model": "Camry",
"item_year": 2023,
"item_active": true,
"item_cond": [ {"title":"excellent","value":"c1"} ],
"item_owner": [ {"type":"workspaceMembers","title":"Alex Kulo","value":1} ]
})
```
- Provide **`formId`** (number) or **`formName`** (string, resolved to its id).
- Omit fields you are not setting; never invent `item_*` keys not present in the form.
- Display-only fields (`label`/`button`/`image`) get no `data` entry.
## Read an actor
```
getActor(actorId="<UUID>", filter="id,title,data") # by UUID
getActorByRef(formId=42, ref="car-…", filter="id,title,data") # by (form, ref)
```
Use `filter` to fetch only the fields you need — actor `data` can be large.
## Update an actor
```
updateActor(
formId=42, actorId="<UUID>",
data={ "item_year": 2024, "item_active": false }) # only these keys change
```
`updateActor` is a **partial** update of `data` — keys you include are replaced, the rest
are untouched. You can also set `title`/`description`/`color`/`status`/`ref`. To clear a
multi-value field, send `[]`.
**Re-key by `ref`.** `updateActor(formId, actorId, ref="…")` sets or changes the actor's
external reference — a stable business key, **unique per form** — the same key `createActor`
accepts, but now editable after creation. Then address the actor by its key instead of its
UUID: `getActorByRef(formId, ref)`. Omit `ref` to leave it unchanged.
**Embed a smart form (script) in an actor.** Set `appId` (on `createActor` / `updateActor`)
to a Smart Form (CDU/Script app) actor id — the actor's card then renders/runs that smart
form; `appSettings` `{autorun, expired, users, groups, fullWidth}` tunes it. See
`simulator-smart-forms`.
**Rich `description` (BBCode).** An actor's `description` renders **BBCode** — chips like
`[actor=<otherActorId>]Label[/actor]` (nested actor card) and `[application=<smartFormId>]Label[/application]`
(smart-form chip), plus formatting (`[b]`, `[color=…]`, `[h2]`, `[ul][*]…[/ul]`, `[url=…]`) and
`[md]…[/md]` for markdown. Fetch the environment's exact tag set with **`getBbcodeTags`**.
**BBCode is processed only OUTSIDE `[md]` blocks.** The reverse matters too: a `description` is rendered as **BBCode by default, not markdown**, so any markdown you write (`##`, `-`, `**bold**`, tables) MUST be wrapped in `[md]…[/md]` or it shows as literal text — applies to every `createActor`/`updateActor` `description`, Events actors (chats/meetings/tasks) included (e.g. `description="[md]## Agenda\n- item[/md]"`). See `docs/entities/reactions.md` → "Embedding".
## Holes — empty placeholder nodes
A **hole** is an empty placeholder slot on a graph, rendered as a hollow node: it marks a
position in the structure that is **not yet filled**. A hole becomes a normal actor once it is
filled with data — ideal for laying out a template / "company DNA" graph up front and turning
each slot into a real actor as the data arrives.
```
createActor(formId=3279, title="Budget", hole=true) # create a hole
updateActor(formId=3279, actorId="<UUID>", hole=true) # turn an existing actor into a hole
updateActor(formId=3279, actorId="<UUID>", hole=false) # fill it — hole → normal actor
```
- `hole` is a top-level **boolean** on `createActor` / `updateActor`; omit it → default `false`.
- It is independent of `status` and `data` (a hole can still carry a `title`). `hole=false`
alone flips a hole back to a normal node.
- Place a hole on a layer like any node (e.g. `manageLayerActors` — see `simulator-graph`).
## Status & delete
```
setActorStatus(actorId="<UUID>", status="verified")
deleteActor(actorId="<UUID>") # irreversible — confirm with the user first
```
---
## Search & filter
### `searchActors` — free-text across the workspace
```
searchActors(accId="ws_xxx", query="camry", limit=20, filter="id,title,formId")
```
Best for "find the actor named …". Run before `createActor` to avoid duplicates.
### `filterActors` — list/rank a form's actors, optionally by an account balance
```
# All actors of a form, newest first
filterActors(formId=42, orderBy="updated_at", withStats=true)
# Data-field filter on the actor data
filterActors(formId=42, q="status=active", status="verified,pending")
# Rank by an account's CURRENT balance, scoped to one anchor actor's neighbours
filterActors(
formId=42,
linkedToActorId="<anchor UUID>", # only actors linked to this one (both directions)
accountNameId="<account-name UUID>",
currencyId=9,
amountFrom=1000, # balance >= 1000
orderBy="balance", orderValue="DESC",
withStats=true)
# Only the CHILD actors of a node (e.g. expand/collapse a node's children)
filterActors(formId=42, linkedToActorId="<anchor UUID>", linkedToActorDirection="children")
# ...or only its parents: linkedToActorDirection="parents"; omit / "both" = either direction (default)
```
- `q` filters on actor **data** fields; `search` does full-text on the title; `status`
filters by status.
- Balance filtering is **current balance only**. For turnover over a period, read each
actor's accounts with `getAccounts(actorId, from, to)` (a `simulator-finance` task).
- Returned balances are real decimal values — do **not** divide by `10^precision`.
### `searchLayerActors` — search within one layer
```
searchLayerActors(actorId="<layer UUID>", query="camry")
```
---
## End-to-end example
```
# 1. Resolve the template and its field ids
searchForms(accId="ws_xxx", q="Car") → formId 42
getForm(formId=42, filter="id,title,sections") → field ids: item_make, item_year, …
# 2. Avoid a duplicate
searchActors(accId="ws_xxx", query="Camry 2023")
# 3. Create the record
createActor(formId=42, title="Toyota Camry 2023",
data={ "item_make":"Toyota", "item_model":"Camry", "item_year":2023 })
# 4. (optional) attach an account — see simulator-finance
createAccount(actorId="<new UUID>", nameId="<aname>", currencyId=1, accountType="fact")
```
## Reference Documents
| Path | When to read |
|---|---|
| `$CLAUDE_PLUGIN_ROOT/docs/entities/actors.md` | Actor `data` protocol + per-class value shapes |
| `$CLAUDE_PLUGIN_ROOT/docs/entities/forms.md` | Field-class catalogue / dynamic select sources |
| `$CLAUDE_PLUGIN_ROOT/docs/entities/search.md` | Search & filter internals |
## Tips
- Always `getForm` first — `data` keys are the form's field `id`s, not titles.
- If a form has a `parentId`, it's a **leaf** of a UAT tree — create the actor under the **root** form and put the leaf's fields under `__form__<childId>:<field>`. Symptom of using the wrong root: `400: Form <id> is not UAT`.
- Dynamic-`select` values reference real ids; resolve them, don't guess.
- `createActor` accepts `formName` (resolved in the active workspace) when you don't have the id.
- `updateActor` is partial; `deleteActor` is irreversible — confirm first.
- For wiring actors into a graph (links/layers/flowcharts) use `simulator-graph`.
- `getCorezoidProcesses(actorId)` lists the Corezoid processes shared to an actor via its access API keys — i.e. the functions/processes that actor can call.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!