Weekly content plan from an Agent Completion: output_schema in Python
Ask the Sume agent for a week of post ideas as typed JSON. Python uses urllib, a required generation_spend_cap_usd, output_schema and a polling loop.

To get a week of content ideas from the Sume agent as typed JSON, POST /v1/agent/completions with an instruction, a required generation_spend_cap_usd, and an output_schema, then poll GET /v1/agent-runs/{id} until the run is terminal. The call returns 202 with a receipt, not a chat reply, so the Python below has a loop.
Use a completion when the task changes each week. If the same recipe repeats and only the inputs change, a Format run is the saved version of it; if only the clock decides, a schedule is.
The request
The cap has no default: omit it and the call fails with 400 invalid_request. The schema follows the strict rules: object root, additionalProperties: false, every property in required.
import json, os, time, urllib.request
H = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"], "Content-Type": "application/json"}
def call(path, body=None):
req = urllib.request.Request("https://api.sume.com" + path, headers=H,
data=json.dumps(body).encode() if body else None)
with urllib.request.urlopen(req) as r:
return json.load(r)["data"]
schema = {"name": "weekly-plan", "schema": {"type": "object", "additionalProperties": False,
"required": ["posts"], "properties": {"posts": {"type": "array", "items": {
"type": "object", "additionalProperties": False, "required": ["day", "idea"],
"properties": {"day": {"type": "string"}, "idea": {"type": "string"}}}}}}}
run = call("/v1/agent/completions", {"instruction": "Plan five short video posts for next week.",
"generation_spend_cap_usd": 2, "output_schema": schema})
while run["status"] in ("queued", "processing"):
time.sleep(10)
run = call("/v1/agent-runs/" + run["id"])
print(run["status"], json.dumps(run["output"])[:200])Reading the result
- Statuses are
queued,processing,completed,failed,canceled. - A completed run fills
outputagainst your schema;artifactsandusagecome with it. If the output could not satisfy the schema,outputisnullandoutput_errorsays why. - Media URLs inside
outputare durablemedia.sume.comHTTPS URLs. - Cancel with
POST /v1/agent-runs/{id}/cancel.
Limits worth knowing
| Item | Behaviour |
|---|---|
| Cap | generation_spend_cap_usd is required, per run |
| Model | Only sume-agent |
| Thread | Each completion starts a fresh thread; assistant turns are rejected |
| Scopes | agent_completions:write to create, :read to read; service-account keys cannot create |
| Streaming | Not available yet |
Does and does not
Sume runs the agent and returns the plan. It does not post for you, and it does not remember last week's plan unless you send it in instruction or input. input is written whole to /workspace/inputs/sume-action-input.json and treated as data, never as instructions, so put the prior week's topics there.
Sources
Related posts
More in Agents
- Agent retry budget for paid video calls: stop on 402
An agent that calls a paid video API needs three counters: submits, estimated dollars and consecutive 402s. The stop rule, and how Sume's spend cap backs it up.
- Claude Code 2.1.288 background session fix: Sume jobs keep running
Claude Code 2.1.288 fixed background sessions ending on plugin reload. A Sume job outlives the session; how to find it and avoid paying twice.
- Claude Code mcp_tool hook skipped on SessionStart: Sume balance check
Claude Code's mcp_tool hooks are skipped on SessionStart and Setup because no MCP client exists yet. Run a Sume balance check at PreToolUse instead.
- Claude Code plugin agents honor disallowedTools: block Sume paid tools
Since 2.1.288 plugin-defined agents run with their own prompt, tools, disallowedTools and effort. A reviewer agent that can read Sume jobs but never create one.
Written by Sume