
Extruct Api
- 30 installs
- 104 repo stars
- Updated July 1, 2026
- extruct-ai/gtm-skills
Helps with backend & apis tasks.
About
extruct-api is a Claude Code skill for backend & apis. It helps solo builders move faster with AI-assisted coding.
- extruct-api
- Backend & APIs
- AI-coding skill
Extruct Api by the numbers
- 30 all-time installs (skills.sh)
- Ranked #3,375 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Jul 31, 2026 (Skillselion catalog sync)
npx skills add https://github.com/extruct-ai/gtm-skills --skill extruct-apiAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 30 |
|---|---|
| repo stars | ★ 104 |
| Last updated | July 1, 2026 |
| Repository | extruct-ai/gtm-skills ↗ |
What it does
Helps with backend & apis tasks.
Files
Extruct API
Use <extruct_api_cli> for supported Extruct operations. Do not construct raw HTTP requests for operations the CLI already supports.
Extruct AI is a company discovery and research platform for finding, enriching, and evaluating companies. Its core workflows are semantic search, lookalike search, and Deep Search for company discovery, plus AI Tables for repeatable company and people enrichment, scoring, and contact-finding workflows.
Source Of Truth
Use the bundled CLI and the instructions in this skill as the default path.
When behavior is unclear, when the user asks for a capability that may not be covered here, or when the request may depend on recently changed API behavior, consult the official Extruct API reference as the source of truth:
- https://www.extruct.ai/docs/api-reference/introduction
Decision rule:
- if the CLI already supports the operation, use the CLI
- if the CLI does not cover the operation or the documented behavior here conflicts with the live API, defer to the official API docs
Resolve The Bundled CLI First
<extruct_api_cli> means the absolute path to the bundled CLI script for this skill.
- Resolve it from the directory that contains this
SKILL.md. - In shell or Bash tool calls, prefer the resolved absolute path, not
scripts/extruct-apirelative to the workspace root. - All command examples below use
<extruct_api_cli>as shorthand for that resolved absolute path.
Example:
/absolute/path/to/skills/extruct-api/scripts/extruct-api auth userCore Workflow
This section covers the default operating intent of the skill: identify the Extruct object the user is working with, choose the right execution path, inspect before mutating, and use the CLI to carry the task through to completion.
1. Resolve <extruct_api_cli> first, then establish API access. Before the first authenticated CLI call in a conversation, run <extruct_api_cli> auth user. If it fails, run <extruct_api_cli> healthcheck to distinguish credential problems from connectivity issues. 2. Classify the request into the right Extruct path:
- if the user provides an Extruct table URL or a raw table UUID, treat it as an existing table operation first
- if the user provides an Extruct task URL or a raw task UUID, treat it as an existing Deep Search task first
- company discovery: semantic search, lookalike search, or Deep Search
- existing table operation: inspect, add/update rows or columns, run, poll, read
- company-table workflow: enrich or score companies in a reusable table
- people workflow: find people at companies or enrich existing people rows
3. If the user already has a table or task, inspect it before mutating it. Default inspection is tables get, columns list, and a small tables data page. When you only need a surgical read, add --columns on the first tables data call instead of fetching the full row payload. 4. Start from the inline command and payload examples in this file. If a payload spans more than a few lines, prefer --payload-file. Read references/column-guide.md before designing or changing columns. 5. Carry async work through to completion with tables poll or deep-search poll, then summarize the final result or API error in plain language, including IDs, counts, and the next relevant object when it matters.
If any request shape, field name, response contract, or endpoint capability is uncertain while executing this workflow, re-check the official API reference before proceeding:
- https://www.extruct.ai/docs/api-reference/introduction
Resolve Extruct Identifiers
Users may provide Extruct objects as raw IDs or as dashboard URLs.
Interpret them as follows:
- if the user provides an Extruct table URL such as
https://app.extruct.ai/tables/<table_id>orhttp://app.extruct.ai/tables/<table_id>, treat the path segment after/tables/as the table id - if the user provides an Extruct task URL such as
https://app.extruct.ai/tasks/<task_id>orhttp://app.extruct.ai/tasks/<task_id>, treat the path segment after/tasks/as the Deep Search task id - if the URL includes extra path segments, query params, or fragments, still extract the id from the
/tables/<table_id>or/tasks/<task_id>segment - if the user provides a raw table UUID, use it directly as the table id
- if the user provides a raw task UUID, use it directly as the task id
- do not ask the user to restate an id that is already present in the URL
- when a table URL is present, default to the existing-table workflow unless the user explicitly asks for a new table or a search workflow
- when a task URL is present, default to the Deep Search task workflow unless the user explicitly asks to start a new search task
Example:
User request:
Add a funding column to http://app.extruct.ai/tables/0a1a669a-9a40-497c-bb00-d49dd8ee5b74Resulting table id:
0a1a669a-9a40-497c-bb00-d49dd8ee5b74First CLI reads:
<extruct_api_cli> tables get 0a1a669a-9a40-497c-bb00-d49dd8ee5b74
<extruct_api_cli> columns list 0a1a669a-9a40-497c-bb00-d49dd8ee5b74
<extruct_api_cli> tables data 0a1a669a-9a40-497c-bb00-d49dd8ee5b74 --limit 20 --offset 0User request:
Check results for https://app.extruct.ai/tasks/d530c3ad-626c-4d7b-ab15-181d4058e4f8Resulting task id:
d530c3ad-626c-4d7b-ab15-181d4058e4f8First CLI reads:
<extruct_api_cli> deep-search get d530c3ad-626c-4d7b-ab15-181d4058e4f8
<extruct_api_cli> deep-search results d530c3ad-626c-4d7b-ab15-181d4058e4f8 --limit 20 --offset 0Choose The Right Company-Finding Path
Semantic Search
Use semantic search when the user describes a market, ICP, category, product, or use case in natural language.
Typical asks:
- "search Extruct for AI procurement startups"
- "find German fintech companies in Extruct"
- "show me B2B treasury automation companies"
Commands:
<extruct_api_cli> companies search --query "vertical SaaS for logistics procurement" --limit 20
<extruct_api_cli> companies search --query "enterprise sales AI" \
--filters '{"include":{"country":["United States"]},"range":{"founded":{"min":2018}}}' \
--offset 20 --limit 20Use --filters when the user specifies geography, city, company size, or founded range. Pass a JSON object like one of these as the --filters value.
{
"include": {
"country": ["United States"],
"size": ["51-200", "201-500"]
}
}{
"range": {
"founded": {
"min": 2018,
"max": 2024
}
}
}If search filters or pagination behavior appear different from the guidance here, verify current request and response details in the official API reference before guessing.
Lookalike Search
Use lookalike search when the user already has a reference company and wants similar companies. Prefer domains or URLs for --company-identifier unless a prior Extruct response already gives you a UUID.
Typical asks:
- "find companies similar to Stripe in Extruct"
- "lookalike search from ramp.com"
Commands:
<extruct_api_cli> companies similar --company-identifier extruct.ai --limit 20
<extruct_api_cli> companies similar --company-identifier stripe.com \
--filters '{"include":{"country":["United Kingdom"]}}'Pagination uses the same --offset and --limit behavior as semantic search.
If identifier handling is unclear for a specific seed company or the live API behavior differs, verify the current lookalike-search request contract in the official API reference.
Deep Search
Use Deep Search when the user wants a higher-precision asynchronous company search, wants explicit criteria, or is comfortable waiting for a task.
Typical asks:
- "run Deep Search for B2B revenue intelligence vendors"
- "find high-conviction AI procurement startups and show me the first result"
Create a task:
<extruct_api_cli> deep-search create --payload '{"query":"AI procurement startups serving enterprise finance teams","desired_num_results":25}'Create a task with explicit criteria:
<extruct_api_cli> deep-search create --payload-file criteria.jsoncriteria.json:
{
"query": "vertical SaaS companies serving freight forwarding",
"desired_num_results": 25,
"criteria": [
{
"key": "has_logistics_focus",
"name": "Logistics Focus",
"criterion": "Company serves freight forwarding or logistics operations."
},
{
"key": "b2b_fit",
"name": "B2B Fit",
"criterion": "Company sells primarily to business buyers."
}
]
}Inspect, poll, read results, or request more:
<extruct_api_cli> deep-search list --limit 20
<extruct_api_cli> deep-search get <task_id>
<extruct_api_cli> deep-search poll <task_id>
<extruct_api_cli> deep-search results <task_id> --limit 20 --offset 0
<extruct_api_cli> deep-search resume <task_id> --payload '{"desired_new_results":25}'Deep Search notes:
deep-search resultscan be read while the task is still runningdeep-search pollcompletes whenstatus == "done"oris_exhausted == true- if the user wants follow-on enrichment, move shortlisted domains into a company table
- if the payload spans more than a few lines or includes
criteria, prefer--payload-fileover inline--payload
If Deep Search payload fields, task states, or resume behavior are unclear, verify them against the official API reference before constructing raw fallback requests.
Read references/finding-companies.md when the task is a fuller company-discovery workflow instead of a single search command.
Operate Existing Tables
Use these commands when the user already has a table and wants to inspect it, change rows or columns, run new work, or read results.
Typical asks:
- "add a funding column to this Extruct table"
- "poll this Extruct table until it finishes"
- "show me the first 20 rows from this table"
- "rerun only the new columns on this table"
If table payload shape, row schema, or run behavior is unclear, check the official API reference before mutating live tables:
- https://www.extruct.ai/docs/api-reference/introduction
Create A Table
Use this when the user needs a new table before doing anything else.
<extruct_api_cli> tables create --payload '{
"name":"Target Accounts",
"kind":"company"
}'Inspect Before Mutating
If the user supplied a table URL, extract the table id first and use that id for all CLI commands below.
<extruct_api_cli> tables list --limit 20
<extruct_api_cli> tables get <table_id>
<extruct_api_cli> columns list <table_id>
<extruct_api_cli> tables data <table_id> --limit 20 --offset 0
<extruct_api_cli> tables data <table_id> --limit 20 --offset 0 --columns company_name,company_website
<extruct_api_cli> rows get <table_id> <row_id>Update, Clone, Or Delete A Table
Update metadata:
<extruct_api_cli> tables update <table_id> --payload '{
"name":"Target Accounts - Updated",
"description":"High-priority accounts for enrichment"
}'Clone or delete:
<extruct_api_cli> tables clone <table_id> --schema-only
<extruct_api_cli> tables delete <table_id> --yes--schema-only clones the columns and structure without copying row data. Without --schema-only, clone copies both schema and rows.
Add, Update, Or Delete Rows
Use company domains or URLs as the safest input on company tables. Default to "run": false while iterating so you can inspect rows and columns before spending more work. Only switch to "run": true when the user explicitly wants add-and-run in one step. Before deleting, inspect either the specific row with rows get or a small tables data page so you only remove the intended records.
Create rows:
<extruct_api_cli> rows create <table_id> --payload '{
"rows":[
{"data":{"input":"extruct.ai"}},
{"data":{"input":"stripe.com"}}
],
"run":false
}'Update rows:
<extruct_api_cli> rows update <table_id> --payload '{
"rows":[
{
"id":"<row_id>",
"data":{"input":"https://extruct.ai"}
}
],
"run":false
}'Delete rows:
<extruct_api_cli> rows delete <table_id> --yes --payload '{
"rows":[
"<row_id_1>",
"<row_id_2>"
]
}'Row-deletion notes:
- deletion is bulk and row-ID based
rows deleterequires--yes- a successful response returns the deleted row IDs
Add, Update, Or Delete Columns
Read references/column-guide.md before designing or changing columns. Prefer built-in column kinds before custom prompts.
If a column kind, payload field, or validation rule in this skill looks stale, verify the current table and column contract in the official API reference before retrying.
Add a simple research column:
<extruct_api_cli> columns add <table_id> --payload '{
"column_configs":[
{
"kind":"agent",
"name":"Latest Funding",
"key":"latest_funding",
"value":{
"agent_type":"research_pro",
"prompt":"What is the latest funding round for the company? Return round type, amount, date, and lead investors when available.",
"output_format":"text"
}
}
]
}'Update a column:
<extruct_api_cli> columns update <table_id> <column_id> --payload '{
"kind":"agent",
"name":"Latest Funding",
"key":"latest_funding",
"value":{
"agent_type":"research_pro",
"prompt":"What is the latest funding round for the company? Return round type, amount, date, and lead investors when available.",
"output_format":"text"
}
}'Delete a column:
<extruct_api_cli> columns delete <table_id> <column_id> --yesRun And Poll
Default incremental run:
<extruct_api_cli> tables run <table_id>
<extruct_api_cli> tables run <table_id> --payload '{
"mode":"new",
"columns":["<column_id_1>","<column_id_2>"]
}'Poll and then read a small result page:
<extruct_api_cli> tables poll <table_id>
<extruct_api_cli> tables data <table_id> --limit 20 --offset 0
<extruct_api_cli> tables data <table_id> --limit 20 --offset 0 --columns company_name,latest_fundingTable-operation defaults:
- prefer
mode: "new"when iterating on an existing table - bare
tables run <table_id>is shorthand for{"mode":"new"} - supported run modes are
new,all, andfailed - pass explicit column ids when the user only wants new work
- inspect a small result page before scaling out, and use
--columnswhenever you only need a surgical slice of the data - do not rerun the whole table unless the user explicitly wants that
Choose The Right Table Kind
When creating a table, choose the kind from the entity the rows represent:
company: use when rows are companies and the user wants company research, enrichment, scoring, or company-to-people branchingpeople: use when rows are people or contacts and the user wants email, phone, LinkedIn, or derived people fieldsgeneric: use only when rows are neither companies nor people
For generic tables:
- the CLI fully supports create, update, run, and read operations
- this skill gives less prescriptive guidance because there are no company/people built-ins to lean on
- use
references/column-guide.mdmore directly and design prompts, dependencies, and output formats explicitly
Research Companies With Tables
Use company tables when the user wants custom enrichment over a set of companies or wants to run repeatable company research workflows.
Company table notes:
companytables automatically includeinput,company_profile,company_name, andcompany_website- use domains or URLs as row inputs whenever possible
- built-in company columns usually remove the need to create basic identity fields yourself
If the user needs a fresh company table, create one:
<extruct_api_cli> tables create --payload '{
"name":"Target Accounts",
"kind":"company"
}'Then use the existing-table commands above to:
1. add company rows 2. add custom research columns from references/column-guide.md 3. run only the new column ids with mode: "new" 4. poll and inspect a small results page
Read references/researching-companies.md when the task is a full company-research workflow instead of a single table operation.
Find People At Companies
Use this path when the user starts from companies and wants decision-makers, leadership, or contactable people.
If child-table behavior, finder output shape, or workflow handoff details differ from what this skill expects, verify the current API behavior in the official API reference.
Start from a company table, then add a company_people_finder column:
<extruct_api_cli> columns add <company_table_id> --payload '{
"column_configs":[
{
"kind":"company_people_finder",
"name":"Decision Makers",
"key":"decision_makers",
"value":{
"roles":["VP Sales","sales leadership","revenue operations"]
}
}
]
}'Run only the new finder column and poll:
<extruct_api_cli> tables run <company_table_id> --payload '{
"mode":"new",
"columns":["<people_finder_column_id>"]
}'
<extruct_api_cli> tables poll <company_table_id>Then inspect the parent table to find the generated child people table in child_relationships, and continue there:
<extruct_api_cli> tables get <company_table_id>The parent company table will also show the people-finder cell result, but the child people table is the place to continue downstream enrichment.
Use broader role families for coverage, such as sales leadership, and exact titles for narrower targeting, such as VP Sales. Read references/finding-people-at-companies.md when the task is a full company-to-people workflow.
Research People
Use this path when the user already has people rows or already has a generated child people table and now wants enrichment, contact data, or derived fields.
Typical asks:
- "find work emails for these people"
- "add phone numbers to this people table"
- "classify these contacts by department and seniority"
People-table notes:
peopletables automatically includeinput,full_name,role, andprofile_url- full name, current role, and LinkedIn URL is the safest
input - include current role when available
- for
email_finderorphone_finder,company_websitemust exist under the exact keycompany_website - on
peopletables, customagentcolumns can usellm,research_reasoning, andlinkedin;research_prois not allowed
If people-table capabilities, supported column kinds, or enrichment requirements appear to have changed, verify them in the official API reference before proceeding.
Create a standalone people table with local website context:
<extruct_api_cli> tables create --payload '{
"name":"Target Contacts",
"kind":"people",
"column_configs":[
{
"kind":"input",
"name":"Company Website",
"key":"company_website"
}
]
}'Add people rows:
<extruct_api_cli> rows create <people_table_id> --payload '{
"rows":[
{
"data":{
"input":"Jane Doe, VP Sales, https://linkedin.com/in/jane-doe",
"company_website":"extruct.ai"
}
}
],
"run":false
}'Add contact or derived columns:
<extruct_api_cli> columns add <people_table_id> --payload '{
"column_configs":[
{
"kind":"email_finder",
"name":"Work Email",
"key":"work_email"
},
{
"kind":"phone_finder",
"name":"Direct Phone",
"key":"direct_phone"
}
]
}'Run, poll, and inspect:
<extruct_api_cli> tables run <people_table_id> --payload '{
"mode":"new",
"columns":["<column_id_1>","<column_id_2>"]
}'
<extruct_api_cli> tables poll <people_table_id>
<extruct_api_cli> tables data <people_table_id> --limit 20 --offset 0Read references/researching-people.md when the task is a full people-research workflow.
Troubleshooting And Recovery
Auth Or Connectivity Fails
Run:
<extruct_api_cli> auth user
<extruct_api_cli> healthcheckIf auth user fails, the token or account context is wrong. If healthcheck fails too, treat it as connectivity or service health.
If the auth flow, expected status codes, or healthcheck contract has changed, defer to the official API reference.
Search Results Are Too Broad
- add
--filtersfor country, city, size, or founded range - switch from semantic search to lookalike if a reference company exists
- switch from semantic search or lookalike to Deep Search if the user wants a tighter, higher-conviction shortlist
Lookalike Results Feel Wrong
- use a domain or URL instead of a company name when possible
- confirm the seed company is the correct one before judging the output
Column Creation Fails
Common causes:
- unresolved prompt references such as
{pricing_notes}pointing at a missing key - wrong table kind for the column kind
- invalid
jsoncolumns without anoutput_schema
Check references/column-guide.md before retrying.
Cells Never Start Or Stay Idle
Common causes:
- upstream dependency cells are not done yet
- the table is missing required context
- the run targeted the wrong columns
Checks:
- inspect the table header and current columns
- verify the same rows have
donecells in any upstream dependency columns - keep dependency chains short
- rerun only the intended new columns with
mode: "new"
Email Or Phone Enrichment Fails On People Tables
Check that:
- the row has strong person context in
input company_websiteexists under the exact keycompany_website- the row belongs to the intended company
Results Are Hard To Use Downstream
- split multi-job prompts into separate columns
- use
select,multiselect,numeric,money,date,grade, orjsoninstead of defaulting totext - use the simplest format that captures the business value; do not pack Extruct explanation or source metadata into
jsonunless the user explicitly wants those fields as table data - derive downstream classifications with
llmafter researching the source fact once
Retry Behavior
- if the CLI returns
429, treat it as billing or quota rejection, not a tight-loop retry signal - if the CLI returns a
5xx, wait 5-10 seconds and retry once
Global Flags
--prettyfor human-readable JSON--timeout <seconds>to override request timeout--base-url <url>to override the API base URL- these flags can be placed before the resource, after the resource, or after the final action; for example:
<extruct_api_cli> tables list --limit 20 --pretty
References
references/column-guide.md: column design rules plus a comprehensive library of good column configsreferences/finding-companies.md: choose and operate semantic search, lookalike, and Deep Searchreferences/researching-companies.md: build or extend company research tables safelyreferences/finding-people-at-companies.md: branch from company tables into people workflowsreferences/researching-people.md: enrich standalone or generated people tables- official Extruct API reference: https://www.extruct.ai/docs/api-reference/introduction
interface:
display_name: "Extruct API"
short_description: "Company discovery, Deep Search, AI tables, enrichment, and people workflows"
icon_small: "./assets/logo.svg"
icon_large: "./assets/logo.svg"
brand_color: "#4D56F3"
default_prompt: "Use Extruct API to search, enrich, or operate on Extruct companies, tables, or people workflows."
Column Guide
Use this guide whenever you need to create, update, or debug Extruct columns. It blends the public column-management guidance with a comprehensive template library so the agent can both choose the right column behavior and copy good configs.
Contents
1. Design order 2. Before you run 3. Pick the right column kind 4. Agent types 5. Purpose-built column kinds 6. Output formats 7. Dependencies and prompt writing 8. Troubleshooting 9. Recommended defaults 10. Template library 11. Common chains
Design Order
When creating a column, make decisions in this order:
1. pick the table kind 2. pick the column kind 3. if needed, pick the agent type 4. pick the output format 5. decide what the column should depend on 6. write the prompt
Many column mistakes come from doing this in reverse.
Before You Run
Before you add or run columns:
- confirm the table kind, row count, and existing columns
- prefer built-in column kinds before designing custom prompts
- add only the columns you actually need
- run only the new column ids when iterating
- review a small sample of completed rows before scaling out
For full workflows, read:
researching-companies.mdfinding-people-at-companies.mdresearching-people.md
Pick The Right Column Kind
Use the simplest column kind that matches the data you want Extruct to return.
Use input When You Already Have The Value
Use input for values that already exist in your own system, such as:
- company website
- raw company name
- manual notes
- local scoring metadata
If you already have the value, store it as input instead of spending credits asking Extruct to rediscover it.
Use agent When Extruct Needs To Research, Reason, Or Transform
Use a custom agent column when you want Extruct to return:
- a new fact it needs to research
- a summary or normalization of upstream row data
- a classification into a fixed set of options
- structured output such as
select,money,grade, orjson
Prefer Purpose-Built Column Kinds When They Already Match The Job
Use purpose-built kinds for jobs Extruct already knows how to do:
company_people_finderemail_finderphone_finderreverse_email_lookuplinkedin
Agent Types
Extruct agent types are not interchangeable.
| Agent type | Use this when you want Extruct to return... | Notes |
|---|---|---|
research_pro | a company answer grounded in the right company context | default for ordinary company enrichment |
research_reasoning | a judgment-heavy or ambiguous answer that needs careful reasoning | best when the hard part is reasoning, scoring, or disambiguation |
llm | a transformation of data already present in the row | no web research |
linkedin | data from a known LinkedIn company or person URL | use after you already have the right LinkedIn URL |
research_pro
Use research_pro when you want Extruct to return a company answer such as:
- pricing and packaging information
- funding or valuation
- target segments
- recent news
- product or use-case research
- closest competitors
- canonical company URLs such as LinkedIn or careers pages
Why it is usually the default on company tables:
- it gathers or confirms company context before answering
companytables automatically injectcompany_nameandcompany_website
research_reasoning
Use research_reasoning when the hard part is judgment rather than fact collection, for example:
- choosing the official site from messy candidates
- assigning a custom score
- deciding whether the company is SMB, mid-market, or enterprise
- ranking or reasoning across evidence
llm
Use llm when you want Extruct to transform data already present in the row.
Use it for:
selectvalues derived from upstream notes- summaries of several upstream columns
- normalized versions of messy evidence
- structured
jsonderived from row context
linkedin
Use linkedin when the row already has a known LinkedIn URL and you want LinkedIn-derived data.
Typical pattern:
1. use research_pro to find the right LinkedIn URL 2. use linkedin to fetch LinkedIn data 3. use llm to summarize or classify that data
Important people-table rule:
- on
peopletables, customagentcolumns can usellm,research_reasoning, andlinkedin research_prois not allowed onpeople-table customagentcolumns
Purpose-Built Column Kinds
Built-In Company Intelligence
company tables automatically create and fill:
company_profilecompany_namecompany_website
You usually should not create those manually.
company_people_finder
Use this when you want Extruct to return people at a company by role.
It:
- starts from company context
- expands role intent into realistic title variants and searches
- creates or updates a related
peopletable
Both exact titles and broader role families are supported.
Use broader role families for coverage:
sales leadershipengineering leadershiprecruitingproduct leadership
Use precise titles for a narrower search:
CEOVP SalesHead of EngineeringRevenue Operations
email_finder And phone_finder
These are provider-backed contact lookups, not research agents.
They require:
full_nameprofile_urlcompany_website
company_website can come from:
- a parent company row, or
- a local people-table input column keyed exactly
company_website
reverse_email_lookup
Use this when you already have an email and want Extruct to resolve person or profile data from that email.
It uses a top-level email_column_key field and does not use a value block.
Output Formats
Choose the output format that best matches the data you want Extruct to return later.
| Output format | Use this when you want Extruct to return... | Example |
|---|---|---|
text | prose, notes, or short bullet summaries | company description |
url | one canonical URL | careers page |
email | one email address | normalized email from row context |
select | exactly one allowed option | pricing model |
multiselect | zero or more allowed options | markets served |
numeric | a count or measured value | employee count |
money | structured financial data | annual revenue |
date | an exact or partial date | founded date |
phone | one international-format phone number | direct phone |
grade | a 1-5 score with explanation | ICP fit |
json | nested structured output | competitor list |
Guidance:
- use the simplest output format that preserves the business value of the answer
- use
textfor short prose meant to be read directly - use
selectormultiselectwhen the answer should be constrained to labels - use
numeric,money,date,url,email, orphonewhen the answer is a single typed value - use
moneyfor revenue, ARR, valuation, or funding - use
gradefor bounded scoring rubrics - prefer separate columns when fields will be filtered, sorted, exported, or automated independently
- Extruct already returns sources and explanation outside the answer; do not duplicate that wrapper metadata inside
output_schema - do not add provenance-only fields such as
sources,source_url,evidence_url,reasoning,why, ornotesunless those fields are themselves durable business outputs the user wants to keep in the table - prefer
selectfor bounded classifications even when you also want justification; Extruct's response metadata already carries the supporting explanation - use
jsonwhen the user wants one structured answer with multiple fields that naturally belong together in one cell, such as status plus supporting URL, a competitors array, structured social profiles, launches list, or a product catalog slice
Anti-pattern:
- do not model a bounded decision as
jsonjust to carry evidence alongside it - bad fit: remote hiring as
{status, evidence_url, notes} - better fit:
remote_hiring_statusasselectwith labels such asyes,no,mixed,unclear - if the user wants one compact structured answer, a small
jsonobject is fine - if downstream workflows need each field to be independently filterable, sortable, exportable, or automatable, split them into separate columns
Good fit for json:
remote_hiring_statuspluscareers_page_urlin one structured answer- a competitors array with per-competitor fields such as
name,domain, andshort_reason - structured social profiles that naturally belong together in one answer
- a product catalog slice or launch list with repeated items
Rule of thumb:
- one bounded label ->
select - one typed scalar -> typed non-
jsonformat - a few fields that the user wants as one cohesive answer ->
json - several independently reusable fields -> separate columns
- one nested object or repeating list ->
json
If you set output_format to json, output_schema is required.
Dependencies And Prompt Writing
Dependencies
For custom agent columns, dependencies come from:
- prompt references such as
{pricing_notes} extra_dependencies
Auto-Injected Baseline Context
On company and people tables, Extruct automatically injects baseline context for custom agent columns.
For company tables:
company_namecompany_website
For people tables:
full_nameprofile_urlrole
What this means:
- on
companyandpeopletables, most prompts should be plain natural-language instructions with no variables - add explicit prompt references only when a column must read another custom column
- on
generictables, explicit references are often the clearest choice
Prompt Writing Rules
Each column should ask Extruct for one job.
Good prompts are:
- specific
- narrow
- explicit about what should come back
- grounded in the current row or explicit upstream inputs
Prompt-design rule:
- ask Extruct for the business answer, not for duplicated provenance
- do not ask the model to return URLs, notes, source lists, or reasoning inside the answer just to justify the answer; Extruct already returns sources and explanation outside the answer
- if explanatory text is itself the business output, it is fine to store it explicitly
- if the user wants one compact structured answer, a small
jsonobject is fine; split into separate columns only when the fields need to be used independently downstream - prefer one bounded output per column unless the user explicitly wants one cohesive multi-field answer
Research prompt pattern:
Find the company's official careers page URL. Return the single best URL only.Chained llm prompt pattern:
Classify the company's pricing approach into exactly one option based on:
Pricing Notes
---
{pricing_notes}
---Bounded classification pattern:
Classify the company's remote hiring status into exactly one option:
yes, no, mixed, unclear.
Return the label only.Split-column pattern:
Classify the company's remote hiring status into exactly one option:
yes, no, mixed, unclear.
Return the label only.If the user also wants the careers page URL in the same answer, returning a small json object is fine. Split it into separate columns only when the status and URL need to be used independently downstream.
Competitor discovery pattern:
Find the company's closest competitors and alternatives.
Prefer companies that solve the same core problem for a similar buyer.
Return one object with a competitors array.
Each competitor should include name, domain, and short_reason.
If you are not confident a company is a real competitor, leave it out.Bad JSON vs better typed-columns example:
Bad fit:
{
"status": "mixed",
"evidence_url": "https://company.example/careers",
"notes": "Some roles are remote-friendly."
}Better split when the fields need to be used independently:
remote_hiring_status -> select
careers_page_url -> urlCompact JSON example for one combined answer:
{
"remote_hiring_status": "mixed",
"careers_page_url": "https://company.example/careers"
}Good JSON example:
{
"competitors": [
{
"name": "Ramp",
"domain": "ramp.com",
"short_reason": "Targets the same finance automation buyer."
}
]
}Troubleshooting
Unresolved Column References
Cause:
- the prompt references a missing column key
Fix:
- create the source column first
- or change the prompt to reference an existing key
Column Is Not Compatible With Table Kind
Common examples:
company_people_finderon apeopletableresearch_procustomagentcolumn on apeopletable
Cells Never Start Running
Cause:
- upstream dependency cells are not done
Fix:
- inspect the source columns first
- keep dependency chains short
Results Are Hard To Use Downstream
Cause:
- too many
textoutputs - bounded answers were packed into
jsonwith evidence or commentary fields
Fix:
- move repeated decisions into
select,multiselect,numeric,money,date,phone,grade, orjson - keep provenance in Extruct's wrapper metadata unless the user explicitly needs it as table data
A Column Feels Expensive
Cause:
- you used web research for a transformation problem
Fix:
- research the source fact once
- derive downstream fields with
llm
Recommended Defaults
If you are unsure:
- default to
companytables - default to built-in column kinds when available
- default to
research_profor company facts - default to
llmfor downstream transformations - default to the simplest output format that preserves downstream value
- default to
selectfor bounded classifications - default to separate columns over one
jsonblob when the fields have different jobs - default to
jsononly when the answer is naturally multi-field domain data - do not model Extruct wrapper metadata such as sources or explanation inside
output_schemaunless the user explicitly wants those fields in the table - default to natural-language prompts with no variables on
companyandpeopletables - add explicit references only for intentional chaining or on
generictables
Template Library
Copy one or more of these objects into column_configs, then adjust name, key, allowed options, and prompt wording as needed.
Wrapper example:
{
"column_configs": [
{
"kind": "agent",
"name": "Description",
"key": "company_description",
"value": {
"agent_type": "research_pro",
"prompt": "Describe what the company does in under 25 words.",
"output_format": "text"
}
}
]
}Notes before you copy:
- on
companyandpeopletables, required columns are created automatically - on those tables, custom agent columns get baseline context injected automatically
- most prompts on
companyandpeopletables should not mentioncompany_name,company_website,full_name,profile_url, orroleexplicitly - if a template below references another column, that dependency is intentional
Company Research
Description
{
"kind": "agent",
"name": "Description",
"key": "company_description",
"value": {
"agent_type": "research_pro",
"prompt": "Describe what the company does in under 25 words.",
"output_format": "text"
}
}ICP Summary
{
"kind": "agent",
"name": "ICP Summary",
"key": "icp_summary",
"value": {
"agent_type": "research_pro",
"prompt": "Identify the company's ideal customer profile. Summarize the primary buyer, company type, and likely use case in 2-3 short bullet points.",
"output_format": "text"
}
}Employee Count
{
"kind": "agent",
"name": "Employee Count",
"key": "employee_count",
"value": {
"agent_type": "research_pro",
"prompt": "How many employees does the company currently have?",
"output_format": "numeric"
}
}Annual Revenue
{
"kind": "agent",
"name": "Annual Revenue",
"key": "annual_revenue",
"value": {
"agent_type": "research_pro",
"prompt": "What is the company's latest annual revenue or ARR? Prefer the most recent reliable figure and use revenue, not total funding.",
"output_format": "money"
}
}Founded Date
{
"kind": "agent",
"name": "Founded Date",
"key": "founded_date",
"value": {
"agent_type": "research_pro",
"prompt": "When was the company founded?",
"output_format": "date"
}
}Pricing Notes
{
"kind": "agent",
"name": "Pricing Notes",
"key": "pricing_notes",
"value": {
"agent_type": "research_pro",
"prompt": "Summarize the company's pricing model and publicly visible price points as a short bulleted list. Include plan names and prices when available.",
"output_format": "text"
}
}Recent News
{
"kind": "agent",
"name": "Recent News",
"key": "recent_news",
"value": {
"agent_type": "research_pro",
"prompt": "List the company's most important news from the last 12 months, newest first. Include date, headline, and URL.",
"output_format": "json",
"output_schema": {
"type": "object",
"properties": {
"articles": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {"type": "string"},
"headline": {"type": "string"},
"url": {"type": "string"}
}
}
}
}
}
}
}Product Launches Last 12 Months
{
"kind": "agent",
"name": "Product Launches",
"key": "product_launches",
"value": {
"agent_type": "research_pro",
"prompt": "List the company's notable product launches from the last 12 months, newest first. Return one object with a launches array. Each launch should include date, name, summary, and url when available. Leave out vague marketing updates that are not real launches.",
"output_format": "json",
"output_schema": {
"type": "object",
"properties": {
"launches": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {"type": "string"},
"name": {"type": "string"},
"summary": {"type": "string"},
"url": {"type": "string"}
}
}
}
}
}
}
}Competitors
{
"kind": "agent",
"name": "Competitors",
"key": "competitors",
"value": {
"agent_type": "research_pro",
"prompt": "Find the company's closest competitors and alternatives. Prefer companies that solve the same core problem for a similar buyer. Return one object with a competitors array. Each competitor should include name, domain, and short_reason. If you are not confident a company is a real competitor, leave it out.",
"output_format": "json",
"output_schema": {
"type": "object",
"properties": {
"competitors": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"domain": {"type": "string"},
"short_reason": {"type": "string"}
}
}
}
}
}
}
}Expansion Signals
{
"kind": "agent",
"name": "Expansion Signals",
"key": "expansion_signals",
"value": {
"agent_type": "research_pro",
"prompt": "Identify and summarize the company's expansion signals using job postings, press releases, new office mentions, executive hires, and product launches. Focus on geographic, product, or market expansion. Return a short evidence-dense summary with dates when available.",
"output_format": "text"
}
}URLs And LinkedIn
LinkedIn Company URL
{
"kind": "agent",
"name": "LinkedIn URL",
"key": "linkedin_company_url",
"value": {
"agent_type": "research_pro",
"prompt": "Find the company's official LinkedIn company page URL.",
"output_format": "url"
}
}LinkedIn Company Data
Requires:
linkedin_company_url
{
"kind": "agent",
"name": "LinkedIn Data",
"key": "linkedin_company_data",
"value": {
"agent_type": "linkedin",
"prompt": "{linkedin_company_url}",
"output_format": "text"
}
}LinkedIn Activity Summary
Requires:
linkedin_company_data
{
"kind": "agent",
"name": "LinkedIn Activity",
"key": "linkedin_activity_summary",
"value": {
"agent_type": "llm",
"prompt": "Summarize the recent LinkedIn activity as a bulleted list with names, dates, and links.\n\nLinkedIn Company Data\n---\n{linkedin_company_data}\n---",
"output_format": "text"
}
}Careers Page URL
{
"kind": "agent",
"name": "Careers URL",
"key": "careers_page_url",
"value": {
"agent_type": "research_pro",
"prompt": "Find the company's official careers or jobs page URL.",
"output_format": "url"
}
}Crunchbase URL
{
"kind": "agent",
"name": "Crunchbase URL",
"key": "crunchbase_url",
"value": {
"agent_type": "research_pro",
"prompt": "Find the company's Crunchbase profile URL.",
"output_format": "url"
}
}Derived llm
Pricing Model
Requires:
pricing_notes
{
"kind": "agent",
"name": "Pricing Model",
"key": "pricing_model",
"value": {
"agent_type": "llm",
"prompt": "Select the company's primary pricing model.\n\nPricing Notes\n---\n{pricing_notes}\n---",
"output_format": "select",
"labels": [
"Free",
"Freemium",
"Subscription",
"Usage-Based",
"Custom Quote",
"One-Time Purchase",
"Marketplace Take Rate"
]
}
}HQ Country From Company Profile
Requires:
company_profile
{
"kind": "agent",
"name": "HQ Country",
"key": "hq_country",
"value": {
"agent_type": "llm",
"prompt": "Extract the company's headquarters country from this company profile.\n\nCompany Profile\n---\n{company_profile}\n---",
"output_format": "text"
}
}Revenue Band
Requires:
annual_revenue
{
"kind": "agent",
"name": "Revenue Band",
"key": "revenue_band",
"value": {
"agent_type": "llm",
"prompt": "Classify the company's revenue into exactly one band based on this structured revenue data.\n\nAnnual Revenue\n---\n{annual_revenue}\n---",
"output_format": "select",
"labels": [
"<$1M",
"$1M-$10M",
"$10M-$50M",
"$50M-$100M",
"$100M-$500M",
"$500M+"
]
}
}Buyer Type
Requires:
company_description
{
"kind": "agent",
"name": "Buyer Type",
"key": "buyer_type",
"value": {
"agent_type": "llm",
"prompt": "Select the company's primary buyer type.\n\nDescription\n---\n{company_description}\n---",
"output_format": "select",
"labels": [
"SMB",
"Mid-Market",
"Enterprise",
"Consumer",
"Developer",
"Public Sector",
"Healthcare Providers",
"Financial Institutions"
]
}
}Prioritization JSON
Requires:
company_profileexpansion_signalsannual_revenuerecent_news
{
"kind": "agent",
"name": "Prioritization",
"key": "prioritization",
"value": {
"agent_type": "llm",
"prompt": "You are a go-to-market analyst. Score ICP fit and buying intent. Return ONLY valid JSON with: icp_fit_score, buying_intent_score, positive_signals, negative_signals, recommended_action, outreach_hook.\n\nCompany Profile\n---\n{company_profile}\n---\n\nExpansion Signals\n---\n{expansion_signals}\n---\n\nAnnual Revenue\n---\n{annual_revenue}\n---\n\nRecent News\n---\n{recent_news}\n---",
"output_format": "json",
"output_schema": {
"type": "object",
"properties": {
"icp_fit_score": {"type": "number"},
"buying_intent_score": {"type": "number"},
"positive_signals": {
"type": "array",
"items": {"type": "string"}
},
"negative_signals": {
"type": "array",
"items": {"type": "string"}
},
"recommended_action": {"type": "string"},
"outreach_hook": {"type": "string"}
}
}
}
}If you want people-finder evidence in downstream scoring, first create a separate llm summary column from the people output, then reference that summary instead of the raw company_people_finder result.
People And Contact
Leadership Finder
{
"kind": "company_people_finder",
"name": "Leadership",
"key": "leadership",
"value": {
"roles": [
"CEO",
"Founder",
"operations leadership",
"revenue leadership"
]
}
}Engineering Leadership Finder
{
"kind": "company_people_finder",
"name": "Engineering Leaders",
"key": "engineering_leaders",
"value": {
"roles": [
"Head of Engineering",
"VP Engineering",
"platform leadership",
"security leadership"
]
}
}Decision Makers
{
"kind": "company_people_finder",
"name": "Decision Makers",
"key": "decision_makers",
"value": {
"roles": [
"VP Sales",
"sales leadership",
"revenue operations",
"business development leadership"
]
}
}Work Email
Requires:
company_website
Configured with kind, name, and key only. No value field is required.
{
"kind": "email_finder",
"name": "Work Email",
"key": "work_email"
}Direct Phone
Requires:
company_website
Configured with kind, name, and key only. No value field is required.
{
"kind": "phone_finder",
"name": "Direct Phone",
"key": "direct_phone"
}Department
{
"kind": "agent",
"name": "Department",
"key": "department",
"value": {
"agent_type": "llm",
"prompt": "Classify this person into the most likely department based on their current role.",
"output_format": "select",
"labels": [
"Executive",
"Engineering",
"Product",
"Design",
"Sales",
"Marketing",
"Operations",
"Finance",
"HR",
"Legal",
"Customer Success",
"Other"
]
}
}Seniority
{
"kind": "agent",
"name": "Seniority",
"key": "seniority",
"value": {
"agent_type": "llm",
"prompt": "Classify this person's seniority level based on their current role.",
"output_format": "select",
"labels": [
"C-Level",
"VP",
"Head",
"Director",
"Manager",
"Individual Contributor",
"Founder"
]
}
}Reverse Email Lookup
{
"kind": "reverse_email_lookup",
"name": "Profile from Email",
"key": "profile_from_email",
"email_column_key": "work_email"
}Scoring
AI-Native Score
{
"kind": "agent",
"name": "AI Native",
"key": "is_ai_native",
"value": {
"agent_type": "research_pro",
"prompt": "Assess this statement about the company: The company is fundamentally AI-native rather than merely adding lightweight AI features. Use the default 1-5 grade scale. If there is not enough evidence to score confidently, return Not found.",
"output_format": "grade"
}
}Enterprise Fit Score
{
"kind": "agent",
"name": "Enterprise Fit",
"key": "enterprise_fit",
"value": {
"agent_type": "research_pro",
"prompt": "Assess this statement about the company: The company clearly sells to enterprise customers. Use the default 1-5 grade scale. If there is not enough evidence to score confidently, return Not found.",
"output_format": "grade"
}
}Competitive Axis Score
{
"kind": "agent",
"name": "SMB vs Enterprise",
"key": "axis_smb_enterprise",
"value": {
"agent_type": "research_reasoning",
"prompt": "Evaluate where this company sits on the spectrum from SMB to Enterprise. Consider pricing, sales model, product complexity, and customer size. Use this scale: 1 = pure SMB, 3 = mid-market, 5 = pure enterprise. If there is not enough evidence to score confidently, return Not found.",
"output_format": "grade"
}
}Common Chains
URL -> LinkedIn Fetch -> Summary
1. linkedin_company_url 2. linkedin_company_data 3. linkedin_activity_summary
Research -> Classification
1. pricing_notes 2. pricing_model
Company -> People -> Contact Enrichment
Use:
finding-people-at-companies.mdresearching-people.md
Finding Companies
Use this playbook when the user wants to discover companies, shortlist a market, or turn a search prompt into company candidates.
All commands below use <extruct_api_cli> as shorthand for the resolved absolute path to this skill's bundled CLI. Resolve that path from the directory containing SKILL.md before running any command.
When To Use It
Use this playbook when the user asks for:
- semantic company discovery from a natural-language query
- similar companies from a known seed company
- a higher-precision asynchronous search with explicit criteria
Do not use this playbook when:
- the user already has a table and wants to operate on it directly
- the user already has companies and wants enrichment columns or scoring
- the user wants people rather than companies
Choose The Right Search Path
Use Semantic Search
Use companies search when the user describes a market, ICP, category, product, use case, or geography in natural language.
<extruct_api_cli> companies search --query "AI procurement startups serving enterprise finance teams" --limit 20Add --filters when the user specifies geography, size, city, or founded range:
<extruct_api_cli> companies search --query "enterprise sales AI" \
--filters '{"include":{"country":["United States"]},"range":{"founded":{"min":2018}}}' \
--limit 20Use Lookalike Search
Use companies similar when the user already knows a reference company.
- prefer a domain or URL as
--company-identifier - use a UUID only when a prior Extruct response already gives you one
<extruct_api_cli> companies similar --company-identifier stripe.com --limit 20Use Deep Search
Use Deep Search when the user wants:
- a more deliberate, higher-precision search
- explicit criteria in the output
- an asynchronous workflow with polling
<extruct_api_cli> deep-search create --payload '{
"query":"AI procurement startups serving enterprise finance teams",
"desired_num_results":25
}'
<extruct_api_cli> deep-search poll <task_id>
<extruct_api_cli> deep-search results <task_id> --limit 20Add criteria when the user wants explicit scoring dimensions:
<extruct_api_cli> deep-search create --payload '{
"query":"vertical SaaS companies serving freight forwarding",
"desired_num_results":25,
"criteria":[
{
"key":"has_logistics_focus",
"name":"Logistics Focus",
"criterion":"Company serves freight forwarding or logistics operations."
}
]
}'Safe Iteration Rules
- keep the first search narrow enough to inspect manually
- add filters before asking for many more results
- for Deep Search, start with a modest
desired_num_resultsunless the user explicitly wants a large run - if the user wants follow-on enrichment, move shortlisted company domains into a company table
What To Inspect
- whether the returned companies actually match the intended market
- whether geography or size needs a filter
- whether a seed company was too ambiguous
- whether the user now wants a shortlist only or a reusable company table
Next Playbooks
- If the user wants enrichment, scoring, or repeatable research over the shortlist, continue to
researching-companies.md. - If the user wants people at the discovered companies, continue to
finding-people-at-companies.md.
Finding People At Companies
Use this playbook when the user starts with companies and wants people, leadership, or contactable decision-makers at those companies.
All commands below use <extruct_api_cli> as shorthand for the resolved absolute path to this skill's bundled CLI. Resolve that path from the directory containing SKILL.md before running any command.
When To Use It
Use this playbook when the user asks to:
- find leadership or decision-makers at a set of companies
- branch from company rows into a people workflow
- generate a child people table from company context
Do not use this playbook when:
- the user already has people rows and wants direct people enrichment
- the user only wants company-level research
Starting State
You need a company table with the correct company rows.
Default Command Flow
Inspect The Company Table
<extruct_api_cli> tables get <company_table_id>
<extruct_api_cli> columns list <company_table_id>Add A company_people_finder Column
Use broader role families when you want more coverage and exact titles when you want a narrower search.
<extruct_api_cli> columns add <company_table_id> --payload '{
"column_configs":[
{
"kind":"company_people_finder",
"name":"Decision Makers",
"key":"decision_makers",
"value":{
"roles":["VP Sales","sales leadership","revenue operations"]
}
}
]
}'Run Only The New Finder Column
<extruct_api_cli> tables run <company_table_id> --payload '{
"mode":"new",
"columns":["<people_finder_column_id>"]
}'
<extruct_api_cli> tables poll <company_table_id>Find The Generated Child People Table
Inspect the parent table and read child_relationships:
<extruct_api_cli> tables get <company_table_id>Typical relationship shape:
{
"child_relationships": [
{
"table_id": "people-table-uuid",
"relationship_type": "company_people"
}
]
}Inspect The People Rows Before Contact Enrichment
<extruct_api_cli> tables get <people_table_id>
<extruct_api_cli> tables data <people_table_id> --limit 20 --columns input,company_websiteSafe Iteration Rules
- run the people finder by itself before adding contact columns
- use broader role families for coverage and narrower titles only when needed
- validate the generated people rows before adding email or phone lookups
- treat the child people table as its own workflow boundary
What To Inspect
- whether the generated roles match the user intent
- whether the profile URLs look plausible
- whether zero-result companies look like true zero-result cases
- whether the child people table has enough quality to justify contact enrichment
Next Playbooks
- Continue to
researching-people.mdto add email, phone, LinkedIn, or derived people columns. - If the company table itself still needs more company research first, go back to
researching-companies.md.
Researching Companies
Use this playbook when the user wants to enrich companies, add custom research fields, or score a set of companies in a reusable table workflow.
All commands below use <extruct_api_cli> as shorthand for the resolved absolute path to this skill's bundled CLI. Resolve that path from the directory containing SKILL.md before running any command.
When To Use It
Use this playbook when the user asks to:
- create a company table and populate it with companies
- add research columns such as funding, pricing, news, or competitors
- rerun only new company research columns
- inspect enriched company-table results
Do not use this playbook when:
- the user only wants one-off company discovery
- the user mainly wants people rather than company-level research
Starting State
You need one of these:
- an existing
companytable, or - a shortlist of company domains or URLs that can become table rows
Default Command Flow
Start A New Company Table
Create the table:
<extruct_api_cli> tables create --payload '{
"name":"Target Accounts",
"kind":"company"
}'Add rows:
<extruct_api_cli> rows create <table_id> --payload '{
"rows":[
{"data":{"input":"extruct.ai"}},
{"data":{"input":"stripe.com"}}
],
"run":false
}'Extend An Existing Company Table
Inspect before mutating:
<extruct_api_cli> tables get <table_id>
<extruct_api_cli> columns list <table_id>
<extruct_api_cli> tables data <table_id> --limit 20
<extruct_api_cli> tables data <table_id> --limit 20 --columns company_name,company_websiteAdd Columns
Design columns from column-guide.md, then add them:
<extruct_api_cli> columns add <table_id> --payload '{ "column_configs":[ ... ] }'Run Only The New Work
<extruct_api_cli> tables run <table_id> --payload '{
"mode":"new",
"columns":["<new_column_id_1>","<new_column_id_2>"]
}'
<extruct_api_cli> tables poll <table_id>Read Results
<extruct_api_cli> tables data <table_id> --limit 20 --offset 0 --columns company_name,latest_fundingSafe Iteration Rules
- prefer built-in company columns before custom prompts
- add a small number of new columns at a time
- use
mode: "new"and explicit column ids for incremental work - inspect a small result page before adding more layers, and project only the fields the user asked about
- if one prompt is trying to do multiple jobs, split it into separate columns
What To Inspect
- whether each column answers one clear question
- whether output formats are structured enough for downstream use
- whether
Not foundbehavior is acceptable - whether a downstream
llmtransformation should replace an extra research column
Next Playbooks
- If the user wants to discover more companies first, go back to
finding-companies.md. - If the user now wants people at the researched companies, continue to
finding-people-at-companies.md.
Researching People
Use this playbook when the user already has people rows, either from a generated child people table or from their own input, and now wants enrichment or contact data.
All commands below use <extruct_api_cli> as shorthand for the resolved absolute path to this skill's bundled CLI. Resolve that path from the directory containing SKILL.md before running any command.
When To Use It
Use this playbook when the user asks to:
- enrich people rows with email, phone, LinkedIn, or derived classifications
- work with a standalone
peopletable - continue after a
company_people_finderworkflow
Do not use this playbook when:
- the user first needs to discover people from companies
- the user only wants company-level research
Starting State
You need one of these:
- a generated child
peopletable, or - a standalone
peopletable with strong person context in each row
Default Command Flow
Create A Standalone People Table When Needed
If the user is not starting from a generated child people table, create a people table. If you want email_finder or phone_finder, include a local input column keyed exactly company_website.
<extruct_api_cli> tables create --payload '{
"name":"Target Contacts",
"kind":"people",
"column_configs":[
{
"kind":"input",
"name":"Company Website",
"key":"company_website"
}
]
}'Add Or Inspect People Rows
The safest standalone input is full name plus LinkedIn URL, and current role if you have it.
<extruct_api_cli> rows create <people_table_id> --payload '{
"rows":[
{
"data":{
"input":"Jane Doe, VP Sales, https://linkedin.com/in/jane-doe",
"company_website":"extruct.ai"
}
}
],
"run":false
}'Inspect before adding more enrichment:
<extruct_api_cli> tables get <people_table_id>
<extruct_api_cli> tables data <people_table_id> --limit 20 --columns input,company_websiteAdd Contact Or Derived Columns
<extruct_api_cli> columns add <people_table_id> --payload '{
"column_configs":[
{
"kind":"email_finder",
"name":"Work Email",
"key":"work_email"
},
{
"kind":"phone_finder",
"name":"Direct Phone",
"key":"direct_phone"
}
]
}'Use column-guide.md for linkedin, llm, department, seniority, and reverse_email_lookup patterns.
Run, Poll, And Read
<extruct_api_cli> tables run <people_table_id> --payload '{
"mode":"new",
"columns":["<column_id_1>","<column_id_2>"]
}'
<extruct_api_cli> tables poll <people_table_id>
<extruct_api_cli> tables data <people_table_id> --limit 20 --columns input,work_email,direct_phoneSafe Iteration Rules
- separate people discovery from contact enrichment
- confirm
company_websiteexists before addingemail_finderorphone_finder - keep contact enrichment and derived
llmtransformations as separate steps when possible - use
--columnson result reads whenever you only need a surgical slice of the data - remember that
research_prois not allowed onpeople-table custom agent columns
What To Inspect
- whether rows have enough person context
- whether profile URLs and company website context line up
- whether email results belong to the expected domain
- whether phone results are sparse but plausible
- whether derived classifications are grounded in the current role
Next Playbooks
- If the user first needs people discovery from companies, go back to
finding-people-at-companies.md. - If the user wants more company-level enrichment around the same accounts, go to
researching-companies.md.