Extend: Agents — sourcing and campaign agents
Lane 6 of Extend Tinbox — agents that source people and run outreach, built on agentic skills over the outreach seam.
Lane 6 is about agents that do outreach — finding the right people (sourcing) and running the campaigns that reach them. The building block is an agentic skill: a tenant-authored tool the assistant, the autopilot, MCP, and the CLI can all call. You give a skill a name, a typed input, and a run function; Tinbox handles the gating, the host allowlist, and exposing it to the model as a callable tool.
The complete example
Here is a real sourcing skill — find founders matching a query and hand them back as prospects:
import { agenticSkill } from "tinbox/cf/skills";
import { z } from "zod";
const sourceFounders = agenticSkill({
id: "source-founders",
label: "Source founders",
description: "Find founders matching a query and return them as prospects.",
requiresEnv: ["APOLLO_KEY"], // gated off until this secret is set
requiresHosts: ["api.apollo.io"], // ctx.fetch host allowlist
inputSchema: z.object({ query: z.string(), limit: z.number().optional() }),
run: async ({ query, limit = 25 }, ctx) => {
const res = await ctx.fetch(
`https://api.apollo.io/v1/people/search?q=${encodeURIComponent(query)}`,
{
headers: { authorization: `Bearer ${ctx.env.APOLLO_KEY}` },
},
);
return await res.json(); // returned data is model-facing
},
});
Register it in config.skills (or, if you ship a plugin, in the plugin's skills / agentTools):
export default defineConfig({
// …
skills: [sourceFounders],
});
Once registered, the assistant, MCP, the CLI, and the autonomous loop can all call source-founders as a tool. Ask the assistant "find me 20 seed-stage founders in Berlin" and it fills the schema, calls run, and reasons over what comes back.
What an agentic skill is
An agentic skill is a tool you author. It has:
id— stable, kebab-case; how the model and the CLI refer to the tool.label— a short human name for the UI.description— shown to the model. This is the tool's prompt: say what it does and when to reach for it, plainly.inputSchema— a Zod object. It typesrun's input and tells the model exactly what arguments to produce. No hand-written JSON Schema.run(input, ctx)— your code. It returns model-facing data — whatever you return is what the model reads next, so return the fields that matter, not raw noise.
The preferred gate is a named Connection:
requires— names the Connections the skill needs. Until every one is configured, the skill is absent from chat, MCP, CLI, and autopilot. A configured client appears atctx.connections[id], with scoped secrets and allowlistedfetch. See the shippedorder-lookupexample.
The legacy low-level scopes remain compatible:
requiresEnv— the skill stays gated off until every named secret is set.source-foundersabove is invisible untilAPOLLO_KEYexists. No key, no tool.requiresHosts— pinsctx.fetchto an allowlist. A call to any host not listed is refused, so a skill can't be talked into exfiltrating to an arbitrary URL.
Inside run, use ctx.fetch (the allowlisted fetch) and ctx.env (your secrets) rather than reaching for globals — that is what keeps the gates real.
Reversibility — what the autopilot may do unattended
Every skill has a reversibility setting:
"reversible"(the default) — safe to undo, so the autopilot may run it without asking. Sourcing a list of people is reversible: it produces prospect rows you can drop."acting"— it takes an outside-visible action (sends mail, posts, charges). Mark it and the autopilot holds it for approval instead of firing it autonomously.
const sendOutreach = agenticSkill({
id: "send-outreach",
label: "Send outreach email",
reversibility: "acting", // held for human approval under autopilot
// …
});
Rule of thumb: if running it twice, or having it run while you're asleep, would embarrass you, it's "acting".
The agent itself
A skill is a tool; an agent is what wields tools toward a brief. Two shapes:
- A per-inbox agent — declare a brief (its goal), the exact tools it may reach (a subset of your skills), and a human-in-the-loop policy (what it may do alone vs. what waits for you).
- The autopilot — run the shared toolset on a schedule, with reversibility deciding what runs unattended.
The full agent model — briefs, tool scoping, approval policy, the four agent surfaces — lives in Agents. This lane only covers the outreach-flavored skills those agents call.
The outreach seam
Sourcing and campaigns ride Tinbox's outreach engine (cold prospects, campaigns), which has a deliberate ownership default:
A cold, BYO-scraped stranger stays campaign-only — a prospect row — and does not pollute your Contacts registry until a touch is earned: an approved send, a reply, a qualification, or a graduation.
So source-founders returning 200 people does not dump 200 rows into Contacts. They sit as prospects; only the ones you actually engage graduate into contacts. Sourcing also credits the real actor — the agent or conversation that did the sourcing — with a provenance event, so a contact page can later show "sourced via agent in YC W26" and you can audit where anyone came from.
Status — be honest: this is the design, and the sourcing seam is partially landed. It rides the coldOutreach feature flag and there is not yet a finished, polished campaign-agent UI. The skill mechanism and the ownership default are real; treat the end-to-end campaign-agent experience as coming, not done.
For the outreach side in depth, see Outreach agents, the one-shot Outreach in one message, and Onboarding cold outreach.
Same mechanism, different intent
The agenticSkill API also powers the agent tools that back dashboards in Lane 5 — Views. The code is identical; the difference is intent. Lane 5 tools answer inbox questions ("how many unreplied threads this week?"). Lane 6 tools reach outward — source people, run campaigns. Pick the lane by what the tool is for, not by how it's built.
Which lane instead?
- To add a tool so the assistant can answer inbox questions (not outreach) → Views (lane 5, /docs/guides/extend-views).
- To set reply behavior on a thread → Replies (lane 2, /docs/guides/extend-replies).
Back to the hub: Extend Tinbox.