Skip to content

SDK Globals

Every task script has access to a set of SDK globals that provide structured interaction with dicode. In Deno tasks, these are passed as properties of the argument to your main() function. In Python tasks, they are available at module level.

params

Read task parameters declared in task.yaml. Values are always strings.

ts
export default async function main({ params }: DicodeSdk) {
  const repo = await params.get("repo");     // string | null
  const all = await params.all();             // Record<string, string>
}
python
name = params.get("name", "World")     # returns default if missing
all_params = params.all()               # dict[str, str]

In async Python tasks, use the _async variants:

python
async def main():
    name = await params.get_async("name", "World")
    all_params = await params.all_async()

API

MethodDenoPython (sync)Python (async)
Get one paramawait params.get(key)params.get(key, default)await params.get_async(key, default)
Get all paramsawait params.all()params.all()await params.all_async()

kv

A persistent key-value store scoped to the task. Values are JSON-serializable and survive across runs. Useful for storing state like counters, last-seen timestamps, or cached data.

ts
export default async function main({ kv }: DicodeSdk) {
  // Read
  const prev = await kv.get("counter") as number | null;

  // Write
  await kv.set("counter", (prev ?? 0) + 1);

  // List all keys (optional prefix filter)
  const all = await kv.list();
  const filtered = await kv.list("github:");

  // Delete
  await kv.delete("old-key");
}
python
# Read
prev = kv.get("counter")

# Write
kv.set("counter", (prev or 0) + 1)

# List all keys (optional prefix filter)
all_keys = kv.list()
filtered = kv.list("github:")

# Delete
kv.delete("old-key")

In async Python tasks:

python
async def main():
    prev = await kv.get_async("counter")
    await kv.set_async("counter", (prev or 0) + 1)
    all_keys = await kv.list_async()
    await kv.delete_async("old-key")

API

MethodDenoPython (sync)Python (async)
Getawait kv.get(key)kv.get(key)await kv.get_async(key)
Setawait kv.set(key, value)kv.set(key, value)await kv.set_async(key, value)
Deleteawait kv.delete(key)kv.delete(key)await kv.delete_async(key)
Listawait kv.list(prefix?)kv.list(prefix="")await kv.list_async(prefix="")

input

The input data from an upstream source. This is set when a task is triggered by a chain (return value of the upstream task) or a webhook (request body). For manual or cron tasks, input is null/None.

ts
export default async function main({ input }: DicodeSdk) {
  const data = input as { event: string; payload: unknown } | null;
  if (data) {
    console.log(`Received event: ${data.event}`);
  }
}
python
# input is available at module level
if input:
    log.info(f"Received event: {input['event']}")

output

Produce visible output for the task run. Output is displayed in the web UI on the run's result page.

ts
export default async function main({ output }: DicodeSdk) {
  // Render HTML (displayed in the result page)
  await output.html("<h1>Hello!</h1>", { data: { key: "value" } });

  // Plain text
  await output.text("Task completed successfully.");

  // Image (base64-encoded content)
  await output.image("image/png", base64EncodedPng);

  // File download
  await output.file("report.csv", csvContent, "text/csv");
}
python
# Render HTML
output.html("<h1>Hello!</h1>", data={"key": "value"})

# Plain text
output.text("Task completed successfully.")

# Image (base64-encoded content)
output.image("image/png", base64_encoded_png)

# File download
output.file("report.csv", csv_content, "text/csv")

In async Python tasks, use the _async variants:

python
async def main():
    await output.html_async("<h1>Hello!</h1>")
    await output.text_async("Done.")

API

MethodDenoPython (sync)Python (async)
HTMLawait output.html(content, opts?)output.html(content, data=None)await output.html_async(content, data=None)
Textawait output.text(content)output.text(content)await output.text_async(content)
Imageawait output.image(mime, content)output.image(mime, content)await output.image_async(mime, content)
Fileawait output.file(name, content, mime?)output.file(name, content, mime=None)await output.file_async(name, content, mime=None)

The data option in output.html() attaches structured data alongside the HTML output. This is useful when webhook task UIs need to read both rendered HTML and machine-readable values.


dicode

Interact with the dicode daemon to run tasks, list tasks, inspect runs, and manage secrets.

WARNING

All dicode methods require explicit permission in task.yaml. See the permissions.dicode section in Tasks.

ts
export default async function main({ dicode }: DicodeSdk) {
  // Run another task (requires permissions.dicode.tasks)
  const result = await dicode.run_task("other-task", { key: "value" });

  // List all registered tasks (requires permissions.dicode.list_tasks)
  const tasks = await dicode.list_tasks();

  // Get recent runs for a task (requires permissions.dicode.get_runs)
  const runs = await dicode.get_runs("other-task", { limit: 5 });

  // Manage secrets (requires permissions.dicode.secrets_write)
  await dicode.secrets_set("MY_API_KEY", "sk-abc123");
  await dicode.secrets_delete("OLD_KEY");
}
python
# Run another task (requires permissions.dicode.tasks)
result = dicode.run_task("other-task", {"key": "value"})

# List all registered tasks (requires permissions.dicode.list_tasks)
tasks = dicode.list_tasks()

# Get recent runs for a task (requires permissions.dicode.get_runs)
runs = dicode.get_runs("other-task", limit=5)

In async Python tasks:

python
async def main():
    result = await dicode.run_task_async("other-task", {"key": "value"})
    tasks = await dicode.list_tasks_async()
    runs = await dicode.get_runs_async("other-task", limit=5)

API

MethodDenoPython (sync)Python (async)
Run taskawait dicode.run_task(id, params?)dicode.run_task(id, params=None)await dicode.run_task_async(id, params=None)
List tasksawait dicode.list_tasks()dicode.list_tasks()await dicode.list_tasks_async()
Get runsawait dicode.get_runs(id, opts?)dicode.get_runs(id, limit=10)await dicode.get_runs_async(id, limit=10)
Set secretawait dicode.secrets_set(key, value)----
Delete secretawait dicode.secrets_delete(key)----

TIP

secrets_set and secrets_delete are available in Deno only. Tasks can write secrets but never read them back -- secret values are injected as environment variables via permissions.env.

Required permissions

yaml
permissions:
  dicode:
    tasks: ["target-task-id"]    # or ["*"] for all
    list_tasks: true
    get_runs: true
    secrets_write: true
    mcp: ["mcp-daemon-id"]

mcp

Call tools on MCP (Model Context Protocol) servers exposed by daemon tasks.

ts
export default async function main({ mcp }: DicodeSdk) {
  // List available tools on an MCP server
  const tools = await mcp.list_tools("my-mcp-daemon");

  // Call a specific tool
  const result = await mcp.call("my-mcp-daemon", "search", {
    query: "test",
    limit: 10,
  });
}
python
# List available tools
tools = mcp.list_tools("my-mcp-daemon")

# Call a specific tool
result = mcp.call("my-mcp-daemon", "search", {"query": "test", "limit": 10})

In async Python tasks:

python
async def main():
    tools = await mcp.list_tools_async("my-mcp-daemon")
    result = await mcp.call_async("my-mcp-daemon", "search", {"query": "test"})

API

MethodDenoPython (sync)Python (async)
List toolsawait mcp.list_tools(name)mcp.list_tools(name)await mcp.list_tools_async(name)
Call toolawait mcp.call(name, tool, args?)mcp.call(name, tool, args=None)await mcp.call_async(name, tool, args=None)

The name parameter is the task ID of the daemon that exposes the MCP server.

WARNING

Requires permissions.dicode.mcp: ["daemon-task-id"] in task.yaml.


Logging

ts
// Use standard console methods
console.log("info level message");
console.warn("warning message");
console.error("error message");
console.debug("debug message");
python
# Use the log global
log.info("info level message")
log.warn("warning message")
log.error("error message")
log.debug("debug message")

In Deno, console.log and console.info are captured at info level. console.warn maps to warn and console.error to error. All log output is streamed in real time to the run log in the web UI.

In async Python tasks, use await log.info_async(...) etc.


HTTP requests

ts
// Native fetch() -- no imports needed
const res = await fetch("https://api.github.com/repos/denoland/deno");
const data = await res.json();
python
# Use any HTTP library (declare it in PEP 723 inline deps)
# /// script
# dependencies = ["httpx>=0.27"]
# ///
import httpx

async def main():
    async with httpx.AsyncClient() as client:
        resp = await client.get("https://api.github.com/repos/denoland/deno")
        data = resp.json()

Deno has fetch() built in. Python tasks can use any HTTP library -- httpx, requests, urllib3 -- declared as a PEP 723 inline dependency.


Environment variables

ts
const token = Deno.env.get("GITHUB_TOKEN");
python
token = env.get("GITHUB_TOKEN")

Environment variables must be declared in task.yaml under permissions.env. See Secrets for how to inject secrets as environment variables.


Return values

Tasks return structured data by returning from the main function (Deno) or assigning to result (Python).

ts
export default async function main({ params }: DicodeSdk) {
  return { status: "ok", count: 42 };
}
python
# Sync: assign to result
result = {"status": "ok", "count": 42}

# Async: return from main()
async def main():
    return {"status": "ok", "count": 42}

Return values are:

  • Stored with the run record and visible in the web UI
  • Passed as input to chained downstream tasks
  • Available via dicode.get_runs() in other tasks