Install
$ agentstack add skill-corezoid-simulator-ai-plugin-simulator-actors ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
> 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="" 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 ids. > - 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_) — not by the field title and not by its secondary key. So the first step of every actor create/update is:
- Resolve the form.
getForm(formId)(orsearchFormsthengetForm). Pass
filter="id,title,sections" to keep it small.
- Map each field you want to set → its
idandclass. - Build
datausing 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":""}] (formFilter = the actors of a given form) | | select → forms | [{"type":"form","title":…,"value":}] | | select → currencies | [{"type":"currency","title":…,"value":}] | | select → accountNames | [{"type":"accountName","title":…,"value":""}] | | select → workspaceMembers | [{"type":"workspaceMembers","title":…,"value":}] | | 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.
Full reference: $CLAUDE_PLUGIN_ROOT/docs/entities/actors.md and …/forms.md.
Multiform actors (__form__:)
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 tocreateActor/updateActor) →
the plain field id, e.g. "name".
- Fields owned by another form →
__form__:.
// 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 `
's field ids,getForm()` 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 is not UAT.
Instead:
- Walk up
parentIdfrom X to the root form of the UAT tree (getFormrepeatedly until
parentId is empty).
- Call
createActorwithformId= the root. - Put the root's own fields under their plain id (
"name"), and the **requested child
form's fields** under the __form__: prefix.
// 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="", # 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) orformName(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 nodataentry.
Read an actor
getActor(actorId="", 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="",
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. To clear a multi-value field, send [].
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=]Label[/actor] (nested actor card) and [application=]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".
Status & delete
setActorStatus(actorId="", status="verified")
deleteActor(actorId="") # 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="", # only actors linked to this one (both directions)
accountNameId="",
currencyId=9,
amountFrom=1000, # balance >= 1000
orderBy="balance", orderValue="DESC",
withStats=true)
qfilters on actor data fields;searchdoes 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="", 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="", nameId="", 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
getFormfirst —datakeys are the form's fieldids, 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__:. Symptom of using the wrong root:400: Form is not UAT. - Dynamic-
selectvalues reference real ids; resolve them, don't guess. createActoracceptsformName(resolved in the active workspace) when you don't have the id.updateActoris partial;deleteActoris 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.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: corezoid
- Source: corezoid/simulator-ai-plugin
- License: MIT
- Homepage: https://simulator.company
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.