Functions (Beta)
Named, versioned TypeScript published from the Harbor inspect runtime.
Beta
Functions are a beta Harbor Cloud surface. Use the defineJob authoring global in files evaluated by hrbr inspect or hrbr exec.
A Function is the reusable form of hrbr exec. Prototype a hosted TypeScript snippet with hrbr exec -f, then publish the stable shape with defineJob and hrbr inspect -f.
Shape
defineJob({
name: "summarize-incident",
description: "Draft a Linear issue from a Sentry issue.",
input: { issueId: "string" },
output: { title: "string", body: "string" },
async run(input) {
const issue = await sentryMcp.getIssue({ id: input.issueId })
const commit = await githubMcp.getCommit({
owner: "acme",
repo: "api",
sha: issue.firstCommit,
})
return {
title: issue.title,
body: `Sentry: ${issue.url}\nLikely cause: ${commit.message}`
}
}
})Publish and run
hrbr inspect -f ./summarize-incident.job.ts
hrbr inspect 'return await hrbr.jobs.inspect({ name: "summarize-incident" })'
hrbr inspect 'return await hrbr.jobs.versions({ name: "summarize-incident" })'Use hrbr exec -f ./summarize-incident.job.ts when you also want a traced execution around the publish path.
Scheduling
Schedules are control-plane triggers that invoke the same Function contract. Discover trigger state with inspect:
hrbr inspect 'return await hrbr.triggers.list({ limit: 20 })'Scheduled runs show up in the same run and trace views as manual invocations.
Functions and Apps
An App route can call a Function by name. The App owns the URL and auth mode; the Function owns the work.
deployApp({
name: "incident-intake",
description: "POST a Sentry issue id and get a draft Linear body back.",
jobs: { summarize: "summarize-incident" },
routes: {
"POST /": { auth: "workspace_member", job: "summarize" },
},
})hrbr inspect -f ./incident-intake.app.tsWhen to write a Function
| Use case | Function | Exec |
|---|---|---|
| Recurring or scheduled | Yes | No |
| Shared across teammates | Yes | No |
| Backs an App route | Yes | No |
| One-off probe | No | Yes |
| Smoke test a plugin | No | Yes |
See Your first Function for the exec-to-function flow.