Pipeline · Flow Engine · Broker
Database migrations, custom multi-agent pipelines, Flow (flow engine) operations, and Broker complete manual. Source:
OPERATION.md§39–§42,src/bridge/routes/pipelines.py,flows.py,flow_templates.py,broker.py,broker_workshop.py,broker_app.py,src/flow/,src/broker/.
Table of Contents
- Database Migration & Upgrade Notes
- Custom Multi-Agent Pipeline (CustomPipeline)
- Flow Engine
- Flow Template CRUD & Editor
- Flow Instance Operations (REST API)
- Resume from Breakpoint
- Broker Overview
- Broker manifest.json Format
- Broker Package Structure (.broker.zip)
- Broker Signing & Verification
- Broker Workshop (Install/Manage/use)
- Broker App Runtime (iframe + SDK)
- Broker Event System & Triggers
- Broker Plugin Sandbox Architecture
- Marketplace Publish & Install
- CLI Command Reference
1. Database Migration & Upgrade Notes
Familiars uses SQLite (default workspace/familiars.db, overridable with FAMILIARS_DB_PATH).
Migration mechanism: Sequential migration scripts under src/storage/migrations/ are executed automatically at startup. The migrator supports both *.sql and *.py carriers.
Current migration coverage: v1 ~ v19:
| Version | Carrier | Content |
|---|---|---|
| v1-v15 | .sql | Core tables: agents, dialogues, nodes, memories, todos, schedules, cron_jobs, etc. |
| v16 | .py | v16__schedule_dedup_and_unique.py — Schedule deduplication + unique constraints |
| v17 | .sql | Supplementary indexes |
| v18 | .sql | broker_clusters + broker_rooms + broker_threads + broker_messages — Broker core tables |
| v19 | .sql | broker_instances + broker_workshop_rooms + broker_triggers + broker_reputation — Broker workshop tables |
| v20+ | .sql/.py | flow_templates, flow_instances, flow_mutations, flow_traces — Flow engine tables |
Upgrade notes:
- First startup of new version: Migrations run automatically at bridge startup; if
migration failedappears in logs → exit and checkworkspace/.bridge.log - WAL files:
familiars.db-wal+familiars.db-shmare WAL mode companion files, must not be deleted individually; copy all three files together when backing up - Backup: The entire
workspace/directory is portable. When moving across machines,SECRET.jsonneeds re-binding (src/base/crypto.pyuses machine salt + Fernet, cannot decrypt on a different machine) - Rollback: No automatic downgrade provided; to return to an older version, restore the entire
workspace/from backup
2. Custom Multi-Agent Pipeline (CustomPipeline)
Entry: Manager Skill Workshop (§38) → select custom_pipeline
2.1 5-Step Wizard
| Step | Name | Description |
|---|---|---|
| 1 | Draft | Fill in pipeline goal + division of labor ideas, can save as draft |
| 2 | Complete | Let manager fill gaps with stronger model, existing fields fully preserved |
| 3 | Preview | View pipeline config + sub-agent identity docs + contract.md |
| 4 | Commit | Create driver agent (appears in AgentRail) + mount all sub-agents |
| 5 | Package/Share | Export .pipeline.zip (entire pipeline + skill recipes) |
2.2 Difference from Regular Agents
- Regular agent: You talk, it does the work
- Pipeline agent: You talk → it delegates to sub-agents → unified response back to you
2.3 Backend API
POST /api/pipelines — Create pipeline
GET /api/pipelines — List all pipelines
GET /api/pipelines/<id> — Pipeline details
DELETE /api/pipelines/<id> — Delete pipeline
POST /api/pipelines/<id>/export — Export .pipeline.zip
POST /api/pipelines/import — Import .pipeline.zip3. Flow Engine
Core file: src/flow/engine.py
3.1 Architecture
FlowEngine uses an owner thread + per-role worker thread model:
- Owner thread (caller thread): The sole writer, receives worker messages, folds them into
FlowState, applies mutations - Worker thread (one per role): Executes WorkUnits on nodes, reports to owner via message queue
Three invariants:
- Only the owner writes: Workers send messages, the owner folds them into state. The sole exception is role status (
Schedulerwrites under its own lock because theagent_statepredicate must be immediately observable) - The graph is frozen, not torn:
rewrite.apply_speccopies → validates → the owner swaps references. Workers hold a complete, self-consistent graph that may be stale but is never half-rewritten - Staleness is caught, not prevented: Workers compare generation before each node; when the graph moves, they automatically relocate
3.2 Mutation Types
| kind | Description | Affects graph? |
|---|---|---|
add_unit | Add work unit | ✅ Rewrites graph |
remove_unit | Remove work unit | ✅ Rewrites graph |
rewire | Change connections | ✅ Rewrites graph |
replace_workflow | Replace entire workflow | ✅ Rewrites graph |
expand_repeat | Expand repeat node | ✅ Rewrites graph |
set_config | Modify configuration | ✅ Rewrites graph |
set_field | Set runtime state field | ❌ Does not affect graph |
3.3 State Machine
pending → running → done
→ failed| State | Meaning |
|---|---|
pending | Instance created, engine not yet started |
running | Engine is executing |
done | Completed normally |
failed | Abnormal termination (crash / timeout / unrecoverable error) |
3.4 Database Tables
| Table | Description |
|---|---|
flow_templates | Template list (id, version, body_json) |
flow_instances | Instances (instance_id, template_id, status, pinned_template_json, base_graph_hash) |
flow_mutations | Change log (seq, kind, spec_json, result_graph_hash) |
flow_traces | Event trace (JSONL file, append-only) |
4. Flow Template CRUD & Editor
Backend: src/bridge/routes/flow_templates.py
Frontend: FlowTemplateList.vue + FlowTemplateEditor.vue (inside CreativeWorkshop)
4.1 API Endpoints
| Endpoint | Description |
|---|---|
GET /api/flow-templates | List (summary rows, no large body) |
POST /api/flow-templates | Create new template |
GET /api/flow-templates/<id> | Get full body (includes template.json + layout.json) |
PUT /api/flow-templates/<id> | Save (validate + persist to disk + SQLite) |
DELETE /api/flow-templates/<id> | Delete (refused if instances exist) |
POST /api/flow-templates/<id>/validate | Dry-run validation (not persisted) |
POST /api/flow-templates/<id>/duplicate | Clone as new id |
GET /api/flow-templates/<id>/export | Download .flow.json |
POST /api/flow-templates/import | Upload .flow.json |
4.2 Bundle Protocol (V2 track layout, schema_version=3)
| Endpoint | Description |
|---|---|
POST /api/flow-templates/preview_bundle | Pre-check .flow.zip bundle (dry-run) |
POST /api/flow-templates/import_bundle | Import .flow.zip or folder path |
GET /api/flow-templates/<id>/export_bundle | Download .flow.zip |
Bundle structure:
my_flow.flow.zip
├── manifest.json Metadata (id, name, version, schema_version)
├── template.json V1 pool layer (nodes + connections)
├── layout.json V2 track/module/variable layer
├── contract.md Collaboration contract (optional)
├── README.md Description (optional)
├── schemas/ Data schemas (optional)
├── docs/ Documentation (optional)
│ ├── DESIGN.md Design document
│ └── DEVELOPMENT.md Development document (→ global FLOW_DEVELOPMENT.md)
└── renderers/ Custom field renderers (optional)
└── *.vue Vue SFC, compiled to ESM JSTemplate storage locations:
- Disk:
workspace/manager/flows/<template_id>/template.json(source of truth, git-trackable) - SQLite:
flow_templatestable (fast listing + instance launch)
4.3 Built-in Templates
- Location:
src/flow/_builtin/<id>/ install_built_ins()syncs at bridge startupread_only: true→ UI splits into System / My lists- System templates hide the delete button but allow copying to "My" for editing
4.4 Per-flow Docs
Each flow has a docs/ directory:
| Endpoint | Description |
|---|---|
GET /api/flow-templates/<id>/docs | List all documents |
GET /api/flow-templates/<id>/docs/<name> | Read document content |
PUT /api/flow-templates/<id>/docs/<name> | Write document (≤1MB) |
DESIGN.md: Flow's design document (returns skeleton template when it doesn't exist)DEVELOPMENT: Always resolves to globalFLOW_DEVELOPMENT.md(is_global: true)
4.5 Custom Field Renderers
renderers/*.vue are Vue SFCs:
src/flow/render/compilerpre-compiles to ESM JS- Chat UI dynamically mounts renderers when input/output field references renderer names
- Used for visual editing of custom field types (e.g., markdown editor, image picker, etc.)
5. Flow Instance Operations (REST API)
Backend: src/bridge/routes/flows.py
5.1 API Endpoints
| Endpoint | Description |
|---|---|
GET /api/flows | List (summary rows, no pinned_template_json) |
GET /api/flows/<instance_id> | Details + most recent N traces (default 20) |
GET /api/flows/<instance_id>/trace | Full trace JSON |
POST /api/flows/<instance_id>/cancel | Cancel (idempotent) |
5.2 List Query Parameters
| Parameter | Type | Description |
|---|---|---|
status | string | Filter: pending / running / done / failed |
template_id | string | Filter by template |
limit | int | Max return count (1-500, default 100) |
5.3 CLI Commands
python main.py flows list # List all flow instances
python main.py flows list --status running # Only running ones
python main.py flows list --template-id content_studio # Filter by template
python main.py flows get flow_xxxxx # Details + last 20 traces
python main.py flows get flow_xxxxx --trace-tail 50 # View last 50 traces
python main.py flows trace flow_xxxxx # Export full trace JSON
python main.py flows trace flow_xxxxx --tail 100 # Only last 100 events
python main.py flows cancel flow_xxxxx # Cancel5.4 Cancel Mechanism
POST /api/flows/<id>/cancel→FlowRepo.request_cancel(instance_id)→ setscancel_requestedflag- Engine gracefully stops after current step completes
- Idempotent: canceling an already-finished instance returns
ok: false, no error
6. Resume from Breakpoint
Core file: src/flow/resume.py
6.1 Mechanism
When bridge crashes causing flow status to remain running, rehydrate() can rebuild engine state from the database:
- Read
pinned_template_jsonto rebuild base graph - Replay change records from
flow_mutationstable inseqorder - Verify
result_graph_hashmatchesapply_and_validateoutput at each step - Any hash mismatch →
FlowResumeError(refuses resume)
6.2 Key Constraints
- Replay = live application: Uses the same
apply_and_validatefunction, impossible for two implementations to diverge set_fieldreplay: Writes toFlowState(does not affect graph hash), replays all set_field mutations in seq order- Fresh instance: Instance with no mutations returns engine based on template base graph (no-op resume)
- Template was modified: Hash mismatch → refuses resume → error
6.3 Data Flow
bridge crash → flow status='running' (stale)
→ user restarts bridge
→ chain detects stale running instance
→ rehydrate(instance_id)
→ repo.get_instance → pinned_template_json
→ apply_and_validate × N mutations
→ verify hash at each step
→ return engine at post-replay state
→ engine.run() continues from where it left off7. Broker Overview
What it is: Broker is Familiars' cluster interconnection layer.
Cluster = one user + all agents under that user. It is Familiars' smallest trust unit: all agents within a cluster share one memory and one permission set, appearing externally as a single signed identity (cluster_id = dev_<device_fingerprint>).
7.1 Four Subsystems
| Subsystem | Core Function | Current Status |
|---|---|---|
| A. Intra-cluster orchestration | Structured collaboration among multiple agents within one cluster: rooms / threads / deals / reputation | ✅ Landed (v18 broker + v19 workshop) |
| B. Application container | Third-party code (plugins / UI / triggers / recipes) as pluggable capabilities hooked into any cluster | ✅ Landed (AST whitelist + subprocess sandbox) |
| C. Distribution & trust | Author signing → static site → user install; Ed25519 + sha256 + author pubkey cross-verification | ✅ Landed (Layer 1 MVP) |
| D. Cross-cluster federation | Message passing between different users' clusters, trusted routing | 🔶 Hooks in place, relay and protocol not implemented |
7.2 Core Data Models
| Concept | Meaning | Implementation |
|---|---|---|
cluster_id | dev_<device_fingerprint> | src/broker/identity.py |
| ClusterCard | Cluster's externally visible card | src/broker/card.py |
| ConsentScope | Capability boundaries granted by cluster to broker | src/broker/scopes.py |
| DomainStore / Ledger | Per-broker domain data + event ledger | src/broker/store.py, ledger.py |
| MatchEngine | Matching engine (rooms/deals) | src/broker/matching.py |
| DealProtocol | State machine: PROPOSED → NEGOTIATING → SETTLED / ABORTED | src/broker/protocol.py |
7.3 Backend API (src/bridge/routes/broker.py)
| Endpoint | Description |
|---|---|
GET /api/broker/brokers | List all registered brokers |
POST /api/broker/brokers/<id>/register | Register cluster |
POST /api/broker/brokers/<id>/deregister | Deregister cluster |
8. Broker manifest.json Format
Required fields:
| Field | Type | Description |
|---|---|---|
broker_id | string | Globally unique ID (also the zip name prefix) |
name | string | Display name |
version | string | Recommended semver |
schema_version | int | Currently 1 |
Recommended fields:
| Field | Type | Description |
|---|---|---|
description | string | One-line description |
domain | string | Domain category |
author_pubkey | string | Author Ed25519 public key (base64) |
ui.entry | string | iframe UI entry HTML (default index.html) |
ui.title | string | Window title |
ui.width / ui.height | int | Window dimensions (px) |
ui.single_instance | bool | Whether single instance |
capabilities_required | string[] | Local APIs declared to cluster: guild / ledger / recipe_call / scheduler |
role_defs | object | Role → capability set mapping |
reputation_dimensions | object[] | Reputation dimension definitions |
permissions | object | Sandbox permissions: extra_modules / rss_mb / cpu_budget_s / rate_limit / timeout_s |
permissions.extra_modules | string[] | Request additional importable modules |
9. Broker Package Structure (.broker.zip)
my_broker.broker.zip
├── manifest.json Required, describes everything about the broker
├── SIGNATURE Required (marketplace enforced), format:
│ <pub_key_b64>\n<sig_b64>\n
├── ui/ Optional, iframe UI directory
│ └── index.html Entry pointed to by manifest.ui.entry
├── plugins/ Optional, *.py loaded via AST whitelist + subprocess sandbox
├── triggers.json Optional, event → plugin/recipe dispatch table
├── recipes/ Optional, recipe archives
├── cover.png Optional, desktop icon
└── README.md OptionalPacker (broker pack) rejects: backslash paths, .. escapes, absolute paths, filenames with strange characters.
10. Broker Signing & Verification
10.1 Signature Domain
Signature = Ed25519(sha256(manifest.json))
After modifying the manifest, re-signing is required. Other files can be changed without invalidating the signature (this is a simplification of the current signature domain).
10.2 CLI Commands
python main.py broker keygen --name <author_name>
→ Generate Ed25519 keypair → ~/.familiars/authors/<name>.key (base64 seed)
→ ~/.familiars/authors/<name>.pub (base64 pubkey)
python main.py broker pack <broker_dir>
→ Package as <broker_id>.broker.zip (includes manifest.json + ui/ + plugins/ etc.)
python main.py broker sign <broker_zip> --author <name>
→ Compute sha256(manifest.json) → Ed25519 sign → write SIGNATURE file
python main.py broker verify <broker_zip>
→ Read SIGNATURE → extract pub_key → verify sha256(manifest.json) signature
→ Cross-check manifest.author_pubkey == pub_key
python main.py broker install <broker_zip>
→ Extract to workspace/manager/brokers/<broker_id>/
→ Register in broker_instances table10.3 Install-time Verification
install_from_url(url) →
Download .broker.zip →
Verify sha256 + Ed25519 signature →
Verify author_pubkey matches →
Extract → register11. Broker Workshop (Install/Manage/Use)
Components: BrokerWorkshopPane.vue + sub-components
Entry: Desktop → App Store icon (apps app → AppsApp.vue)
11.1 Backend API (src/bridge/routes/broker_workshop.py)
Instances (instance management):
| Endpoint | Description |
|---|---|
GET /api/broker_workshop/instances | List installed brokers |
POST /api/broker_workshop/instances/import | Install from uploaded .broker.zip |
POST /api/broker_workshop/instances/install_from_url | Download and install from URL |
GET /api/broker_workshop/instances/<broker_id> | Single broker + manifest |
DELETE /api/broker_workshop/instances/<broker_id> | Uninstall |
GET /api/broker_workshop/instances/<broker_id>/export | Download .broker.zip |
POST /api/broker_workshop/instances/<broker_id>/status | Pause / resume |
Rooms:
| Endpoint | Description |
|---|---|
GET /api/broker_workshop/instances/<id>/rooms | List rooms |
POST /api/broker_workshop/instances/<id>/rooms | Create room |
DELETE /api/broker_workshop/instances/<id>/rooms/<room_id> | Archive room |
Threads:
| Endpoint | Description |
|---|---|
GET /api/broker_workshop/instances/<id>/rooms/<room_id>/threads | List threads |
POST /api/broker_workshop/instances/<id>/rooms/<room_id>/threads | Create thread |
DELETE /api/broker_workshop/instances/<id>/threads/<thread_id> | Archive thread |
Members:
| Endpoint | Description |
|---|---|
GET /api/broker_workshop/instances/<id>/rooms/<room_id>/members | List members |
POST /api/broker_workshop/instances/<id>/rooms/<room_id>/members | Add member |
DELETE /api/broker_workshop/instances/<id>/rooms/<room_id>/members/<cluster_id> | Kick member |
Reputation:
| Endpoint | Description |
|---|---|
GET /api/broker_workshop/instances/<id>/reputation/<cluster_id> | Check reputation score |
POST /api/broker_workshop/instances/<id>/reputation/rate | Rate |
GET /api/broker_workshop/instances/<id>/reputation/<cluster_id>/events | Rating events |
Triggers:
| Endpoint | Description |
|---|---|
GET /api/broker_workshop/instances/<id>/triggers | List triggers |
POST /api/broker_workshop/instances/<id>/triggers | Create trigger |
DELETE /api/broker_workshop/instances/<id>/triggers/<trigger_id> | Delete trigger |
11.2 Source & Read-only
Source (installed_from) | Behavior |
|---|---|
store | 🔒 Marketplace read-only black box: cannot delete/replace/overwrite package-level files. Runtime data (rooms/threads/messages/triggers/reputation) remains accessible |
built_in | Local development, can open directory for secondary development |
user_created | Local development, editable |
imported_zip | Local import, editable |
11.3 Interface Operations
- Installed panel (
InstalledBrokersPanel.vue): Three tiers "Installed / Paused / Not Enabled" - Create (
BrokerCreateModal.vue): Fill name/icon/description + which agents to expose to - Install external package: Drag in / select
.broker.zip→ shows declared permissions → confirm install - Marketplace browsing (
MarketplaceModal.vue): Fetches index.json fromFAMILIARS_MARKETPLACE_URL→ browse/install - Export/share: Installed broker → export .broker.zip
- Enter use: Double-click desktop icon →
BrokerAppWindow.vue(iframe loaded) - Uninstall/pause: Right-click icon → pause (keep data) or uninstall (delete data too)
12. Broker App Runtime (iframe + SDK)
Backend: src/bridge/routes/broker_app.py
Frontend: BrokerAppWindow.vue
12.1 Architecture
Each installed broker's manifest.ui configures it as a sandboxed HTML application:
Desktop shell
└─ BrokerAppWindow.vue
└─ <iframe src="/api/broker_app/<broker_id>/ui/<entry>?token=...">
└─ broker's index.html
└─ <script src="../sdk.js"> → window.familiars RPC facade12.2 SDK RPC Methods
| Method | Description |
|---|---|
me() | { cluster_id } |
manifest() | BrokerManifest |
recipe.list() | { recipes: [{ id, title }] } |
rooms.list() | { rooms } |
rooms.threads(room_id) | { threads } |
rooms.members(room_id) | { members } |
reputation.get(cluster_id) | { scores: [...] } |
storage.get/set/list | Per-broker KV storage |
ui.close/resize/setTitle | Window controls |
12.3 Security
X-Bridge-Tokenpassed to iframe via?token=query param- Content-Security-Policy restricts accessible origins
- Path traversal protection: regex + resolved-parent dual check
- iframe's broker_id injected by parent window, does not trust iframe self-reporting
13. Broker Event System & Triggers
13.1 Event Catalog
Runtime actively emits the following events, routed to handlers matched in the broker_triggers table:
| Event | Payload keys |
|---|---|
app.installed | broker_id, installed_from |
app.started / paused / resumed / uninstalled | broker_id |
message.posted | broker_id, room_id, thread_id?, cluster_id, kind, message_id |
approval.created / voted / decided / withdrawn | approval_id, ... |
deal.transition | deal_id, from_state, to_state, actor, evidence |
member.join / leave / kick | room_id, cluster_id, ... |
reputation.threshold | subject, dimension, from, to, delta |
cron.tick | cron_expr, ts |
custom.<name> | Plugin-defined |
13.2 Trigger Configuration
{
"event": "deal.transition",
"match": {"to_state": "SETTLED"},
"action_kind": "recipe",
"action_ref": "my_recipe",
"enabled": true
}matchfield filters payload:{"to_state": "SETTLED"}only matches events where the corresponding field is equalaction_kind:recipe/plugin_fnaction_ref: Recipe id or plugin function name
13.3 Event Dispatch
event_bus.py receives event → looks up broker_triggers table → matches match → dispatches to action:
recipe→ calls corresponding recipeplugin_fn→ prefers sandbox subprocess RPC, falls back to in-process call on failure
14. Broker Plugin Sandbox Architecture
Files: src/broker/workshop/sandbox/ast_guard.py + dual-track runtime
14.1 Two Checkpoints
- AST whitelist validation (at install time): Rejects forbidden imports, attribute chains,
exec/eval/open, etc. - Runtime sandbox (at startup): Subprocess isolation + resource control
14.2 Module Permissions
Allowed by default: json / math / re / datetime / dataclasses / typing / statistics / collections / collections.abc / enum / functools / itertools / decimal / __future__ / broker_sdk
Can be requested (via manifest.permissions.extra_modules): os / subprocess / requests / aiohttp / httpx / sqlite3 / pathlib / tempfile / hashlib / hmac / base64 / binascii / uuid / secrets / shutil / glob / fnmatch / textwrap / io / copy / pprint / urllib / xml / csv / string / bisect / heapq / operator / random / fractions / warnings / contextlib / abc / types / inspect / argparse
Permanently forbidden (even if requested, not allowed): ctypes / pickle / importlib / code / codeop / pdb / trace / tracemalloc / sys / signal / multiprocessing / threading / asyncio / socket / select / asyncore / asynchat / ssl / mmap / platform / __import__ / eval / exec / compile / open / globals / locals / vars / getattr / setattr / delattr / breakpoint / input / exit / quit
14.3 Dual-track Execution
| Path | Description |
|---|---|
| Legacy in-process | bundle.install() → exec into sys.modules["broker_plugins.<safe_id>.<name>"] |
| Sandbox subprocess | bundle.install_sandboxed() → independent worker subprocess → JSON-RPC (stdin/stdout) |
Event dispatch prefers the sandbox subprocess; falls back to in-process on failure.
14.4 Resource Controls
| Resource | Default | Adjustable (manifest.permissions) |
|---|---|---|
| RSS memory | 512MB | rss_mb |
| CPU budget | 30s window | cpu_budget_s |
| Call rate | 60 calls/minute | rate_limit |
| Single call timeout | 30s | timeout_s |
14.5 Capability Approval Gate
When manifest.permissions declares non-empty capabilities (net / fs_read / fs_write / extra_modules):
- Install requires explicit user approval of capability hash
- Worker starts only after approval
- Not approved →
CapabilityNotApproved - Capability drift (hash changes after manifest upgrade) →
CapabilityDrifted
15. Marketplace Publish & Install
15.1 Server Layout
<marketplace_host>/
├── index.json Index file (lists all available brokers)
├── packages/
│ ├── ventaris.broker.zip
│ ├── example_broker.broker.zip
│ └── ...15.2 index.json Format
{
"version": 1,
"packages": [
{
"broker_id": "ventaris",
"name": "Ventaris",
"version": "1.0.0",
"description": "Guild·Tasks·Medals collaboration platform",
"author_pubkey": "base64...",
"download_url": "https://marketplace.example.com/packages/ventaris.broker.zip",
"cover_url": "https://marketplace.example.com/packages/ventaris_cover.png"
}
]
}15.3 Publish Flow
# 1. Package
python main.py broker pack workspace/manager/brokers/my_broker
# 2. Sign
python main.py broker sign my_broker.broker.zip --author my_name
# 3. Upload to static site
# (Manually upload to marketplace host's packages/ directory, update index.json)15.4 Install Flow
MarketplaceModal → GET <FAMILIARS_MARKETPLACE_URL>/index.json → browse list
→ user selects → POST /api/broker_workshop/instances/install_from_url
→ Download .broker.zip (with browser UA to bypass Cloudflare WAF)
→ Verify sha256 + Ed25519 signature
→ Verify author_pubkey matches
→ Extract to workspace/manager/brokers/<broker_id>/
→ Register in broker_instances table
→ New icon appears on desktop shell15.5 Environment Variables
| Variable | Description |
|---|---|
FAMILIARS_MARKETPLACE_URL | Marketplace static site URL |
16. CLI Command Reference
Broker CLI
python main.py broker keygen --name <author> # Generate keypair
python main.py broker pack <dir> # Package .broker.zip
python main.py broker sign <zip> --author <name> # Sign
python main.py broker verify <zip> # Verify signature
python main.py broker install <zip> # Local install
python main.py broker keys-list # List generated keys
python main.py broker marketplace-index # View marketplace indexFlow CLI
python main.py flows list # List flow instances
python main.py flows list --status running # Filter running
python main.py flows get <instance_id> # Details + trace tail
python main.py flows get <instance_id> --trace-tail 50
python main.py flows trace <instance_id> # Full trace
python main.py flows trace <instance_id> --tail 100
python main.py flows cancel <instance_id> # CancelDeveloper Perspective
- Recipe: Workshop Manual §5-7
- Flow Editor v2: Workshop Manual §6
- Broker development: Repo root
BROKER_DEVELOPMENT.md - SDK reference:
workspace/manager/brokers/SDK.md - Example brokers:
workspace/manager/brokers/starter_broker/(minimal skeleton),workspace/manager/brokers/example_broker/(Vue/Vite project)
