StillMade AIDeveloper docs
Browse documentation · SDK 0.1.0

Hosted text generation

Create a text-generation Block with account BYOK, explicit cost approval, and verified outputs.

Use runtime: "capability" to implement a portable Block that asks StillMade to generate text. The package declares the prompt, instructions, output contract, and fixtures. StillMade owns account authentication, model choice, provider keys, cost confirmation, and execution. This is a separate declarative runtime; fetch, ctx.capabilities, and arbitrary host calls remain unavailable inside JavaScript Blocks.

Create and package

sh
node packages/block-cli/cli.js create ./script-draft capability
node packages/block-cli/cli.js validate ./script-draft
node packages/block-cli/cli.js pack ./script-draft script-draft.stillmade.json

The folder contains stillmade.block.json, src/capability.json, and tests/fixtures.json. A packed JSON contains {manifest, capability, tests} and may include a sandboxed view. No provider key, endpoint, model, billing selection, or receipt belongs in the package. Those fields are rejected.

Download the complete script-draft example. Its manifest uses entry: "src/capability.json", one primary prompt input of type text, one primary script output of type script, and:

json
{"project":[],"capabilities":["text.generate"],"network":[],"filesystem":[],"secrets":[]}

Its capability declaration is:

json
{
  "schemaVersion": 1,
  "operation": "text.generate",
  "prompt": {"$input": "prompt"},
  "system": "Write a concise narration script. Return only the script text.",
  "maxTokens": 1200,
  "output": "script"
}

Declare exactly one prompt input (text, script, or brief) and exactly one output (text, script, or json). Structured prompt inputs contain {"schemaVersion":1,"text":"..."}. A generated script returns that same structured shape; a text output returns a string. Typed ports, primary markers, semantic roles, and scoped project context retain their SDK meaning. A context prompt needs its declared read permission and fresh authorized project snapshot. Do not infer scene or character structure from an unstructured generated script.

Up to three other read-only inputs (for example the saved project script) can also reach the model: list them in the descriptor as "context": ["script"]. StillMade appends their current values after the prompt as delimited data the model is told never to treat as instructions, and the review covers that exact text. An input that is not listed (one a custom view only displays) is never sent.

Conversations

To continue a conversation, declare one optional json input for the earlier turns and bind it as history:

json
{"schemaVersion":1,"operation":"text.generate","prompt":{"$input":"message"},
 "history":{"$input":"history"},"system":"You are a friendly script coach.",
 "maxTokens":800,"output":"reply"}

The history value is up to 20 turns of {"role":"user"|"assistant","content":"..."} (each at most 8,000 characters, 24,000 in total); StillMade sends them between the system instructions and the prompt, and the review covers the exact turns. Other fields and other roles are rejected. A missing history starts a fresh conversation. A custom view or a JavaScript Step can keep the turns and pass them back on the next run.

Structured replies (JSON schema)

For data instead of prose, declare a json output and add schema, the JSON Schema the reply must match:

json
{"schemaVersion":1,"operation":"text.generate","prompt":{"$input":"topic"},
 "system":"You plan short podcast intros.","maxTokens":800,"output":"plan",
 "schema":{"type":"object","additionalProperties":false,"required":["title","script"],
  "properties":{"title":{"type":"string","maxLength":80},
   "script":{"type":"string","maxLength":1200},
   "beats":{"type":"array","items":{"type":"string"},"minItems":3,"maxItems":6}}}}

StillMade tells the model to reply with JSON matching the schema, parses the reply (one surrounding code fence is tolerated) and checks it against the schema before any Step receives it. A reply that does not match fails the run with the first mismatch, for example $.beats: needs at least 3 items. The output port then carries the parsed value, so a JavaScript Block downstream reads input.plan.title directly.

The supported subset is type (one or a list of object, array, string, number, integer, boolean, null), description, title, enum, properties, required, additionalProperties, items, minItems, maxItems, minLength, maxLength, pattern, format (date, date-time, email, uri), minimum and maximum; up to 8 levels deep and 8,192 characters. The system instructions plus the schema instruction must fit in 8,000 characters. Fixture expectations for a json output are {"kind":"json"} with optional includes literal phrases.

Limits: package 256 KiB; prompt 32,000 characters; system instructions 8,000 characters; generated text 32,768 characters; maxTokens integer 1–4096. The operation is one text generation call. Image, audio, video, tool calling, streaming, multi-call agent loops, and arbitrary API requests are not supported by this declaration.

Fixtures and real review

Generated text varies, so fixtures use bounded expectations instead of an exact expected string:

json
[{
  "name": "A short opening narration",
  "input": {"prompt":"Write two narration sentences about a quiet forest at sunrise."},
  "expectations": {"script":{"kind":"script","minLength":20,"maxLength":6000}}
}]

Include 1–3 fixtures. Every output has its matching kind, positive minLength, and maxLength no larger than the output limit. Optional includes contains at most eight required literal strings of at most 256 characters each; regular expressions are not supported. Expectations check the declared interface and bounded behavior, not factual correctness. Review the actual generated result.

Offline validate and pack check source only. pack reports tests: 0, reviewRequired: true, and liveVerified: false. Offline test and preview fail with RUNTIME_UNAVAILABLE; they do not invent a generation result.

Import the JSON or ZIP into StillMade. Test and preview loads available models and payment methods. Review cost obtains a non-billable quote. Only the separate Run tests and sample action submits one call per fixture and one additional sample call. The host displays the complete call count and credit cost first. BYOK uses your encrypted account OpenRouter key; provider usage is billed by that provider and does not consume StillMade generation credits. A missing BYOK key never silently switches to credits.

The server binds the report to your account, exact source digest, inputs, resolved model/payment selection, quote, and execution policy. Every fixture, the separate sample, typed outputs, and expectations must pass. Inspect the sample and source rights, then Confirm Import to install. A client-supplied passed flag or an LLM-written report cannot authorize import or release. AI authoring generates and statically validates a draft; it stops for this hosted review and does not silently run the drafted capability.

Run in a project and recover

Add the reviewed Block to a Project Type to make a Step. Its controls and optional custom interface use the same host execution dialog. Guest UI cannot choose a model, reveal keys, or confirm a quote. Existing matching review results can be reused for project execution, but the current project input always gets its own quote and explicit run confirmation. An expired import review can be reused for a project only after the server revalidates its source, selection, policy, and current project edit access.

Each confirmed request has an account-scoped UUID and durable execution record. The host advances one invocation at a time, retains results, and makes duplicate requests idempotent. An unknown provider outcome is not automatically submitted again. If the creation response is lost, the host finds the original request by its UUID without generating. Continuing an unfinished recovered review requires another explicit Continue generation action; it advances the already confirmed plan, not a new request. Cancellation cannot guarantee that a provider stops already submitted work; completed results are retained, while a cancelled or stale project run cannot be automatically accepted into the project. Failed StillMade-credit charges use the existing idempotent refund ledger. BYOK provider charges follow the provider account and cannot be refunded by StillMade.

A Project Type can be imported after every embedded hosted package receives its own current account review; see review hosted Project Types. This is package admission, not proof that the connected flow ran. Connected automatic runs and unattended future-media jobs stop at the hosted capability boundary; they do not grant advance permission for paid calls.

Publish a verified listing sample

After releasing the Block publicly, choose Publish verified sample in its listing editor. Confirm the public display of that sample's input and output. StillMade reuses the exact retained sample from the release review; it does not call the provider or charge again. The source, account ownership, current runtime policy, quarantine state, complete fixture evidence, and sample contract are checked again. An expired import receipt or a removed API key does not invalidate historical output. Project-run receipts cannot publish a private project sample through this action. The stored preview records the original model and generation time, so it is not represented as a new execution.

Host integration API

js
import {runPackageAsync, prepareCapabilityInvocation, capabilityOutputs}
  from './packages/block-sdk/index.js';

const result = await runPackageAsync(pkg, input, {
  capability: async (reviewedPackage, values, {signal}) => {
    const request = prepareCapabilityInvocation(reviewedPackage, values);
    // Trusted host: authenticate, review cost and approval, execute once,
    // retain the result, then return typed outputs. Never implement this in
    // package code or treat this SDK callback as proof of import review.
    const text = await approvedHostTextRun(request, {signal});
    return {outputs: capabilityOutputs(reviewedPackage, text)};
  }
});

approvedHostTextRun is a host integration placeholder, not an SDK function. The SDK validates declaration and output types; StillMade's server supplies the account receipt and billing guarantees. Optional returned metadata is bounded to 8 KiB and is not an authorization receipt. Without a trusted executor, runPackageAsync fails closed. validateCapability, prepareCapabilityInvocation, capabilityOutputs, validateCapabilityExpectations, and testCapabilityOutputs are the portable validation helpers. They never access a provider.

StillMade's authenticated /api/block-capabilities routes provide options, quotes, review creation/lookup, run creation/status/poll/cancel, and read-only GET /requests/:requestId recovery. Status GETs never execute calls or reconcile refunds; POST polling/cancellation handles those mutations. They use StillMade's credit ledger and encrypted BYOK vault or platform model key; Block authors configure nothing.