scistudio-write-block
SkillFiles & storageUse when the user wants to author a NEW BLOCK FILE — Python source code (a class subclassing Block / ProcessBlock / IOBlock / AppBlock / CodeBlock with typed ports and a config_schema) that goes in ``<project>/blocks/<name>.py``. ALWAYS check if an existing block satisfies the contract first (call list_blocks first and reuse a match).
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the scistudio-write-block skill
What this skill tells your AI
The instructions your AI receives, as published by jiazhenz026/scistudio in src/scistudio/_skills/scistudio/scistudio-write-block/SKILL.md and read by ahel’s review.
Author a project-local custom block. This skill is the task flow; the contract and worked patterns live elsewhere — read them, do not guess:
.scistudio/agent-reference/block-contract.md— base classes; the optional interactive / App / Code shapes; ports,config_schema,runvsprocess_item, Collection helpers..scistudio/agent-reference/public-api.md— canonical import roots. Import from roots only..scistudio/agent-reference/data-types.md— reading/constructing values..scistudio/agent-reference/package-discovery.md— using package types.user-guide/api-reference/— exact signatures of every public symbol.- Worked patterns: call
mcp__scistudio__list_block_examplesthenmcp__scistudio__read_block_sourceto read real, registered blocks for the shape you need (process, io, app, code) and copy the pattern — do not invent a shape the examples already show.
Non-negotiables (full detail in the reference docs)
- Reuse first. Call
mcp__scistudio__list_blocksBEFORE authoring and reuse any block whose I/O contract matches. A PostToolUse hook blocksblocks/*.pywrites iflist_blockswas not called this session. Build new only when nothing fits; justify it in the new block's docstring. - Canonical imports only.
from scistudio.blocks.base import Block, BlockConfig, InputPort, OutputPort,from scistudio.blocks.process import ProcessBlock,from scistudio.core.types import Array, DataFrame, .... Never a deep module path (...base.ports) or an underscore module (_support) — seepublic-api.md. - Concrete port types. Pick the most specific applicable
type; never bare
DataObject/[]for a non-generic block. Callmcp__scistudio__list_typesfirst.scaffold_blockwarns and a PostToolUse hook stderr-warns onDataObjectports — read every warning. run()returnsdict[str, Collection]keyed by output port name.- Not author surfaces: do not subclass
AIBlock/SubWorkflowBlock(they are runtime base classes; for AI-in-workflow the user adds the built-in AI Agent block and configures it). Do not setbase_category(it is inferred).
Block shapes
A block need not be a plain ProcessBlock. These shapes are all available — none
is preferred; pick whichever fits, and reach for a richer one only when it
genuinely helps the user. See block-contract.md for how to author each.
- config parameter — expose a tunable in
config_schemaand read it withconfig.get(...)so the user can reach it. Prefer this over a buried constant for a value the user may want to change; hard-coding is fine when the value is intrinsic or just a convenient default. - interactive (optional) — a block can pause and let the user make a
data-dependent decision in the GUI (route items, mark a region). Reuse a
built-in panel (
core.interactive.data_router,core.interactive.pair_editor) or ship a small custom panel. - AppBlock / CodeBlock — hand the step to an external GUI/CLI tool, or to a project-local script.
Tool-call sequence
mcp__scistudio__list_blocks # reuse check — STOP if a match exists
mcp__scistudio__list_types # pick concrete port types
mcp__scistudio__scaffold_block(name=..., category="process|io|app|code",
input_ports={...}, output_ports={...}) # READ every warnings[] entry
# edit blocks/<name>.py — fill the body per block-contract.md
mcp__scistudio__reload_blocks # re-scan the registry
mcp__scistudio__list_blocks # confirm it appears
mcp__scistudio__run_block_tests type_name="<registered name>" # read pytest output verbatim
category → parent: process→ProcessBlock, io→IOBlock, app→AppBlock,
code→CodeBlock. Every write-class tool returns a next_step — read and follow.
Make it usable — label everything the user sees
The user drives your block from the GUI, where the only thing they see is the
text you put on these fields. Fill all of them with short, clear, human language
— a non-programmer must be able to tell ports and parameters apart (three ports
all typed Image with no names/descriptions are unusable):
| Where users see it | Field(s) to write |
|---|---|
| Palette + node header | block name (a real label, not MyBlock) and one-line description |
| Each input/output port | a distinct name and a description (what flows here, e.g. "raw image" vs "binary mask" vs "overlay") |
| Each parameter panel field | the config_schema property's title (the label) and description (what it does / units / when to change it) |
| In the code | short, plain comments explaining the why, not the obvious |
Distinct names + a one-line description per port and per parameter is the bar.
A value the user may reasonably want to change usually belongs in config_schema
(with a title/description and a sane default) rather than buried as an
unreachable constant — though a hard-coded value is fine when it is intrinsic or
a convenient default.
Mandatory rules
list_blocksFIRST; reuse on a contract match.list_typesbefore choosing port types; concrete types only.- Canonical-root imports only (
public-api.md); no deep paths /_support. - Do not subclass
AIBlock/SubWorkflowBlock; do not setbase_category. - After
scaffold_block, read everywarnings[]. After writing,reload_blocksthenrun_block_tests; read the resultnext_step.
Anti-patterns
- Authoring without
list_blocksfirst. - Deep-path or
_supportimports; bareDataObjectports on a non-generic block. - Subclassing
AIBlock/SubWorkflowBlock, or settingbase_category. run()returning a non-dict; skippingreload_blocks/run_block_tests.- An interactive block declaring
InteractiveMixinwithoutexecution_mode=INTERACTIVE(or vice versa), or missingprepare_prompt/interactive_panel— the registry rejects it at scan time.
Signals
- GitHub stars
- 30
- Forks
- 1
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
scistudio-write-block- Source
- github.com/jiazhenz026/scistudio