Use Cases
Technical reference. This page is for integrations, advanced configuration, or platform operations. For portal tasks, start with the user guide.
A use case turns a plain-language description of a business problem into a runnable, reviewable, publishable bundle — a flow plus the prompt, model policy, policy bundle, and connections it needs — without hand-assembling each piece yourself.
How It Works
- Describe what you want in plain language (for example, “Triage incoming refund requests and flag anything over $500 for review”).
- Orqestra drafts a bundle: an orchestration flow, a prompt, a reference to an approved model policy, a policy bundle, and any connections the flow needs. If your description leaves something ambiguous, you’re asked a short clarifying question first.
- Review the draft: a plain-language summary of what it does, a worked “try it” example, and a “show me what you built” panel that opens each piece in its real editor.
- Publish. If every connection the bundle needs already exists and you’re allowed to use it, the use case goes live immediately. If a connection doesn’t exist yet and you can’t create it yourself, publish still succeeds — the use case moves to a pending state while a request goes to your platform team.
- Once your platform team grants the request, the connection is set up and the use case activates automatically — no separate step on your part.
The generated flow, prompt, and other pieces follow the same shape as hand-authored assets and can be edited normally once you open them.
Using the API
Generate a draft
POST /v1/use-cases/generate is pure — it never creates anything. It
either returns a bundle plan plus a preview of any access gaps, or a
needs_clarification response with a follow-up question.
This uses the same governed platform-generator family as asset and flow
drafting. Orqestra resolves the active production generator release
server-side, requires a synchronous runtime result, validates the nested bundle
plan, and persists nothing on this route. The generator runs under its own
system credential, provisioned automatically at startup — you do not need a
principal binding of your own on the generator workload; authorization is
decided against the target workspace. Missing target-workspace permission or a
policy denial returns 403, a queued-only runtime returns
409 inline_dispatch_unavailable, and a generator that has no active release
or is not fully provisioned returns 503.
curl -X POST "/v1/use-cases/generate?workspace_id=$WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{
"description": "Triage incoming refund requests and flag anything over $500 for review"
}'Response (bundle):
{
"needs_clarification": false,
"bundle": {
"name": "Refund Triage",
"summary": "Classifies refund requests and flags high-value ones for review.",
"flow": { "entry_step": "classify", "steps": [] },
"prompt_template": { "template": "Classify this refund request: {{ inputs.text }}" },
"model_policy_ref": "gpt4-standard",
"connections": ["billing-crm"]
},
"warnings": [],
"gaps": {
"model_policy": { "kind": "reused", "ref": "gpt4-standard" },
"policy_bundle": { "kind": "mint_fresh", "ref": null },
"connections": [{ "kind": "needs_access", "ref": "billing-crm" }],
"redacted": false
},
"generation_id": "9f43b1d1-2f7e-4d64-8b78-0f3b91a4f6f8"
}Create a draft
POST /v1/use-cases persists the bundle a generate call returned. It
re-validates the bundle from scratch rather than trusting the caller’s copy.
curl -X POST "/v1/use-cases?workspace_id=$WORKSPACE_ID" \
-d '{
"source_description": "Triage incoming refund requests and flag anything over $500 for review",
"bundle": { "...": "the bundle from generate" }
}'Refine a draft
POST /v1/use-cases/{use_case_id}/refine REPLACES a draft: it generates a
fresh bundle from the description plus your refinement_context notes,
persists it as a new use case, and archives the one you refined —
superseded_by on the archived predecessor names the successor — all in a
single transaction. Refining never leaves two drafts behind; exactly one
current draft remains.
curl -X POST "/v1/use-cases/{use_case_id}/refine?workspace_id=$WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{
"description": "Triage incoming refund requests and flag anything over $500 for review",
"refinement_context": [{ "note": "Also post high-value ones to Slack." }],
"idempotency_key": "a3f1c0f2-5b6e-4f4a-9f0c-2f2b9a1d7e11"
}'description is the original description, unchanged — the notes are applied
on top of it, not instead of it. The response is the same envelope
generate-and-create returns: the successor draft in use_case, or a
needs_clarification question with use_case: null, in which case nothing
was created and nothing archived.
idempotency_key is required, and it is what makes a refine safe to
retry. Generation can take longer than a client’s timeout, so a caller may
never learn that its call succeeded; retrying with the SAME key returns the
same successor instead of drafting a second one. A key is additionally scoped
to the predecessor it was first used against — presenting it against a
different use case is a client mistake, not a retry, and returns 409 idempotency_key_conflict. Retry the same instruction with the same key;
change the instruction and you need a fresh one.
Only a draft can be refined — a use case that was already replaced,
published, or archived returns 409. Read superseded_by off the detail
route (GET /v1/use-cases/{use_case_id}) to follow a replaced draft to its
successor and refine that one instead.
List and inspect
curl "/v1/use-cases?workspace_id=$WORKSPACE_ID&status=draft"
curl "/v1/use-cases/{use_case_id}?workspace_id=$WORKSPACE_ID"
curl "/v1/use-cases/{use_case_id}/bundle?workspace_id=$WORKSPACE_ID"Pass activation_ready=true instead of status to list only use cases that
are pending access with every connection already resolved — the same query
that drives the activation to-do described below.
bundle is the persisted bundle behind a use case: one row per piece (the
flow, the prompt, the model policy, the policy bundle, and each connection)
with the id you open it by, plus the bound flow’s step ids and types. It is a
separate read from the detail route above because the detail route is polled
while a use case is pending access, and the bundle only changes when its
connections do. workspace_id is required, like the other use-case routes,
and the read is gated on asset.view. A caller who holds asset.view but not
connection.read gets an empty projection with redacted: true rather than a
filtered one — a partial list would disclose how many connections the bundle
has.
Publish, archive, reopen, activate
curl -X POST "/v1/use-cases/{use_case_id}/publish?workspace_id=$WORKSPACE_ID"
curl -X POST "/v1/use-cases/{use_case_id}/archive?workspace_id=$WORKSPACE_ID"
curl -X POST "/v1/use-cases/{use_case_id}/reopen?workspace_id=$WORKSPACE_ID"
curl -X POST "/v1/use-cases/{use_case_id}/activate?workspace_id=$WORKSPACE_ID"publish resolves to active (no gaps) or pending_access (a needs-access
gap was routed to a fresh access request); an unreachable model policy
fails with a 422 and the use case stays a draft. reopen moves a
pending_access use case back to draft and withdraws its outstanding
requests. activate re-runs the activation check on a pending_access use
case whose connections are all resolved — the same action behind the
activation to-do.
Using the SDK
async with OrqestraClient(base_url=url, api_key=key) as client:
generated = await client.use_cases.generate(
workspace_id=workspace_id,
description="Triage incoming refund requests and flag anything over $500 for review",
)
draft = await client.use_cases.create(
workspace_id=workspace_id,
source_description="Triage incoming refund requests and flag anything over $500 for review",
bundle=generated["bundle"],
)
# Refining REPLACES the draft: the successor comes back in `use_case`,
# and `draft` is archived with `superseded_by` naming it — one call, one
# transaction, still exactly one current draft. Retrying with the same
# idempotency_key returns the same successor rather than drafting another.
refined = await client.use_cases.refine(
draft["use_case_id"],
workspace_id=workspace_id,
description="Triage incoming refund requests and flag anything over $500 for review",
idempotency_key=str(uuid.uuid4()),
refinement_context=[{"note": "Also post high-value ones to Slack."}],
)
current = refined["use_case"] # None if it asked a clarifying question
published = await client.use_cases.publish(current["use_case_id"], workspace_id=workspace_id)
# The persisted bundle behind it — asset rows with real editor targets,
# the bound flow's steps, and any still-open connection gaps.
bundle = await client.use_cases.get_bundle(
current["use_case_id"], workspace_id=workspace_id
)
# Approving a pending connection request from the other side:
await client.access_requests.grant(
access_request_id,
workspace_id=workspace_id,
secret_bindings={"api_key": "billing-crm-api-key"},
)Using the CLI
# Generate and save the draft plan
orqestractl use-cases generate ws-1 \
--description "Triage incoming refund requests and flag anything over $500 for review" \
--output draft-plan.json
# Create it — accepts either the generate response or a bare bundle plan
orqestractl use-cases create ws-1 \
--file draft-plan.json \
--source-description "Triage incoming refund requests and flag anything over $500 for review"
# Refine it — one call that REPLACES the draft: a fresh successor is created
# and this draft is archived with superseded_by naming it, in one transaction.
# --idempotency-key is required; re-running with the same one returns the same
# successor instead of drafting another. --refinement-note is repeatable.
orqestractl use-cases refine ws-1 <use_case_id> \
--description "Triage incoming refund requests and flag anything over $500 for review" \
--refinement-note "Route anything from enterprise accounts straight to review" \
--idempotency-key "$(uuidgen)"
# List, inspect, and drive the lifecycle
orqestractl use-cases list ws-1 --status draft
orqestractl use-cases show ws-1 <use_case_id>
orqestractl use-cases bundle ws-1 <use_case_id>
orqestractl use-cases publish ws-1 <use_case_id>
orqestractl use-cases archive ws-1 <use_case_id>
orqestractl use-cases reopen ws-1 <use_case_id>
orqestractl use-cases activate ws-1 <use_case_id>
# Approve a pending connection request from the platform-team side
orqestractl access-requests grant ws-1 <access_request_id> \
--secret-binding api_key=billing-crm-api-keyUsing the Portal
Start from Workloads → Create → Describe with Assistant. Describe what you want in the chat-style intake; if the description leaves something ambiguous you’re asked a short follow-up before a draft appears.
The review card shows a plain-language summary, a worked “try it” example, and a “Show me what you built” panel — expand it to see each piece of the bundle (new, reused, or needing access) and open any of them in its real editor. Refine regenerates the draft from new instructions and REPLACES it: the fresh draft takes over the page and the one you refined is archived, so you never accumulate half-finished drafts. Regenerating discards edits you’ve made in the editor, so you’re asked to confirm first. Publish is the terminal action — once clicked it can’t be interrupted mid-flight.
If publishing needs a connection you can’t create yourself, the use case moves to a pending state: the review card shows an amber “needs access” row and a pending-request count, and the page polls until your platform team resolves it. Once every request is granted, the use case activates on its own and “Try it” switches from the worked example to real execution.
An owner who leaves a draft unfinished sees a “resume your drafted use case” reminder on their home screen; a platform-team member who is the last approver on a pending use case sees an activation reminder there instead, with a one-click action to finish activating it.
Troubleshooting
| Error | Likely cause |
|---|---|
200 on redacted generate | The response is intentionally a redacted preview; unresolved references are shown as needs_admin gaps rather than disclosed |
422 on full-detail generate, generate-and-create, refine, or create | The generated bundle failed schema/business-rule validation or contained a workspace reference that could not be resolved |
422 on redacted generate-and-create or refine | The chained route reached draft instantiation; the response is a value-free error rather than a needs_admin preview |
422 on publish (“model policy…”) | The bundle’s model policy reference is no longer approved or reachable |
Use case stuck at pending_access | A connection request is still awaiting your platform team’s approval |
409 on publish/archive/reopen | The use case isn’t in a status that allows that transition |
409 on refine | The draft was already replaced or published — refine its successor |
404 on any route | The use case (or its id) doesn’t exist in the given workspace |