Simulator Actors logo

Simulator Actors

Organization
corezoid
simulator-actors

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`.

Overview

Publishercorezoid
Repositorysimulator-ai-plugin
Skill namesimulator-actors
Stars
61
Forks
13
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by corezoid on GitHub. Read the source before you install it.

Installation

Install the Simulator Actors AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/corezoid/simulator-ai-plugin/tree/main/plugins/simulator/skills/simulator-actors
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/corezoid/simulator-ai-plugin.git /tmp/simulator-ai-plugin
mkdir -p .claude/skills
cp -r /tmp/simulator-ai-plugin/plugins/simulator/skills/simulator-actors .claude/skills/simulator-actors
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Simulator Actors in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Simulator Actors on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Simulator Actors is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

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 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_<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 / sourceValue in data
edit text / password / email / phonestring — "dsdf@fsdf.com"
edit int / floatnumber — 1
checkboolean — true
radiothe 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/corezoidSyncApiarray of synced options ([] until synced)
multiSelectarray — [{"title":"one","value":"…"},{"title":"two","value":"…"}]
calendar{"startDate":…,"endDate":…,"timeZoneOffset":-180,"sendInvite":false} (unix seconds)
uploadarray of file refs ([] when empty)
label / button / imageno 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

PathWhen to read
$CLAUDE_PLUGIN_ROOT/docs/entities/actors.mdActor data protocol + per-class value shapes
$CLAUDE_PLUGIN_ROOT/docs/entities/forms.mdField-class catalogue / dynamic select sources
$CLAUDE_PLUGIN_ROOT/docs/entities/search.mdSearch & filter internals

Tips

  • Always getForm first — data keys are the form's field ids, 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.

Frequently asked questions

What does the Simulator Actors AI skill do?

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**...

Why use Simulator Actors on TypingMind?

Because you install it once and use it with any model. Simulator Actors is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Simulator Actors in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/corezoid/simulator-ai-plugin/tree/main/plugins/simulator/skills/simulator-actors. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Simulator Actors?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Simulator Actors?

As many as you like. As long as a model supports skills, you can use Simulator Actors with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Simulator Actors AI skill free?

Yes. It is published on GitHub by corezoid under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇