For TechFabric engineers to write posts and case studies from their coding agent; anyone can read
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). The final verification publish_draft needs. With id: the full checks on your saved draft (the judge, the slop classifier and the fact-check), about a minute; call it after lint_draft passes, never to iterate. Each call waits up to 25 seconds and then reports progress: call it again for the answer (nothing runs twice; a client with the tasks extension gets a task). Right after submit_draft it waits while the draft is filed. Without id it checks markdown and files nothing, which publish_draft doesn't count. On next_action confirm, send first_hand_to_confirm back as first_hand: the engineer confirms, never you.
A draft of yours (the idea id from submit_draft): checks its saved text, the final verification publish_draft needs
What the draft is: "post" (the default, a blog post) or "case-study" (content/case-studies, at /case-studies/<slug>). A case study's frontmatter is title, description, sector, stack, track (ai, migration or other) and client when the client register approves naming them or the engineer says the client agreed (client_confirmed); its body opens with ## Challenge, ## Strategy, ## Solution and ## Results, each with a bold one-line statement first. See the editorial_rules resource.
The engineer's own words the draft's claims come from, as text. For a post: what the engineer told you about their own work (what they built, measured, saw and decided, and any result, client or number they gave you), quoted as they said it, and their notes; the fact-check treats these as the author's own account of the work, so a first-hand sentence they don't back is a finding. Never write them yourself: ask the engineer. For a case study: the engineer's own notes and the project's records (README, changelog, metrics they gave you) its numbers come from. Every number in the case study is checked against these; one that isn't here is a finding. A source is not an approval: a client's metric also needs the client register's approval. Ask the engineer for outcome numbers; never invent them. At most 100,000 characters.
The whole post: frontmatter (title, description at least) and body. With id: optional, and must be the saved text
First-hand claims only the engineer can source, which the fact-check flagged first_hand (first_hand_to_confirm): each the sentence exactly as quoted, with what it rests on. Sending it asks the engineer; it never confirms anything on your word. check_draft asks them in their client (an elicitation) where it can, otherwise answers with a question and a one-time confirmation: ask them that question, and only if they say yes, send it back as first_hand_confirmation with the same first_hand. submit_draft and update_draft answer with the question and confirmation too, which come back on check_draft with the id. Never a client's result: a number about a client needs the client's confirmation, as a source.
With first_hand or first_hand_all: how the engineer is asked. Default: a form in their client where it can show one. "token": the question and a one-time confirmation instead, for a UI that asks them itself (an MCP App's button)
Without the tasks extension: how long to wait for the result before answering with progress (default and most 25; a larger value, accepted for older agents, waits 25)
Confirm all listed: true asks the engineer to confirm, in one go, every first-hand claim the last check of this text listed (first_hand_to_confirm), instead of listing them in first_hand. The list is the server's, from that check: a client's result, a client's fact and a known error are never in it and come back apart (first_hand.excluded). It asks as first_hand does (one form showing every claim, or a question and a one-time confirmation to send back with first_hand_all: true); it never confirms anything on your word. Each claim is still recorded on its own under the engineer's name.
Only when the engineer tells you they have the client's confirmation to name the client this draft names (its client:, or a client in its text the register doesn't approve). Recorded under the engineer's name with the draft and its text; never send it on your own judgement. It covers naming the client, not results: numbers still need sources.
Only after asking the engineer and hearing yes: the confirmation an earlier answer gave for exactly this first_hand (first_hand.confirmation). It works once, for ten minutes, for those claims in that text
This tool isn't marked read-only, so it may change something on the server or in an account you connected.
Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). The final verification publish_draft needs. With id: the full checks on your saved draft (the judge, the slop classifier and the fact-check), about a minute; call it after lint_draft passes, never to iterate. Each call waits up to 25 seconds and then reports progress: call it again for the answer (nothing runs twice; a client with the tasks extension gets a task). Right after submit_draft it waits while the draft is filed. Without id it checks markdown and files nothing, which publish_draft doesn't count. On next_action confirm, send first_hand_to_confirm back as first_hand: the engineer confirms, never you.
| Argument | Type | Description |
|---|---|---|
| id | string | A draft of yours (the idea id from submit_draft): checks its saved text, the final verification publish_draft needs |
| kind | string | What the draft is: "post" (the default, a blog post) or "case-study" (content/case-studies, at /case-studies/<slug>). A case study's frontmatter is title, description, sector, stack, track (ai, migration or other) and client when the client register approves naming them or the engineer says the client agreed (client_confirmed); its body opens with ## Challenge, ## Strategy, ## Solution and ## Results, each with a bold one-line statement first. See the editorial_rules resource. |
| images | array | |
| sources | string | The engineer's own words the draft's claims come from, as text. For a post: what the engineer told you about their own work (what they built, measured, saw and decided, and any result, client or number they gave you), quoted as they said it, and their notes; the fact-check treats these as the author's own account of the work, so a first-hand sentence they don't back is a finding. Never write them yourself: ask the engineer. For a case study: the engineer's own notes and the project's records (README, changelog, metrics they gave you) its numbers come from. Every number in the case study is checked against these; one that isn't here is a finding. A source is not an approval: a client's metric also needs the client register's approval. Ask the engineer for outcome numbers; never invent them. At most 100,000 characters. |
| markdown | string | The whole post: frontmatter (title, description at least) and body. With id: optional, and must be the saved text |
| first_hand | array | First-hand claims only the engineer can source, which the fact-check flagged first_hand (first_hand_to_confirm): each the sentence exactly as quoted, with what it rests on. Sending it asks the engineer; it never confirms anything on your word. check_draft asks them in their client (an elicitation) where it can, otherwise answers with a question and a one-time confirmation: ask them that question, and only if they say yes, send it back as first_hand_confirmation with the same first_hand. submit_draft and update_draft answer with the question and confirmation too, which come back on check_draft with the id. Never a client's result: a number about a client needs the client's confirmation, as a source. |
| confirm_via | string | With first_hand or first_hand_all: how the engineer is asked. Default: a form in their client where it can show one. "token": the question and a one-time confirmation instead, for a UI that asks them itself (an MCP App's button) |
| wait_seconds | integer | Without the tasks extension: how long to wait for the result before answering with progress (default and most 25; a larger value, accepted for older agents, waits 25) |
| first_hand_all | boolean | Confirm all listed: true asks the engineer to confirm, in one go, every first-hand claim the last check of this text listed (first_hand_to_confirm), instead of listing them in first_hand. The list is the server's, from that check: a client's result, a client's fact and a known error are never in it and come back apart (first_hand.excluded). It asks as first_hand does (one form showing every claim, or a question and a one-time confirmation to send back with first_hand_all: true); it never confirms anything on your word. Each claim is still recorded on its own under the engineer's name. |
| client_confirmed | boolean | Only when the engineer tells you they have the client's confirmation to name the client this draft names (its client:, or a client in its text the register doesn't approve). Recorded under the engineer's name with the draft and its text; never send it on your own judgement. It covers naming the client, not results: numbers still need sources. |
| first_hand_confirmation | string | Only after asking the engineer and hearing yes: the confirmation an earlier answer gave for exactly this first_hand (first_hand.confirmation). It works once, for ten minutes, for those claims in that text |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [],
"properties": {
"id": {
"type": "string",
"description": "A draft of yours (the idea id from submit_draft): checks its saved text, the final verification publish_draft needs"
},
"kind": {
"enum": [
"post",
"case-study"
],
"type": "string",
"default": "post",
"description": "What the draft is: \"post\" (the default, a blog post) or \"case-study\" (content/case-studies, at /case-studies/<slug>). A case study's frontmatter is title, description, sector, stack, track (ai, migration or other) and client when the client register approves naming them or the engineer says the client agreed (client_confirmed); its body opens with ## Challenge, ## Strategy, ## Solution and ## Results, each with a bold one-line statement first. See the editorial_rules resource."
},
"images": {
"type": "array",
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"alt": {
"type": "string",
"description": "What the image shows, for its alt text and caption"
},
"data": {
"type": "string",
"description": "The image's bytes, base64 (PNG, JPEG, WebP or GIF, at most 10 MB). Required by submit_draft; check_draft needs only the name."
},
"name": {
"type": "string",
"description": "The file name the post refers to the image by, e.g. pipeline.png"
}
},
"additionalProperties": false
},
"maxItems": 10
},
"sources": {
"type": "string",
"description": "The engineer's own words the draft's claims come from, as text. For a post: what the engineer told you about their own work (what they built, measured, saw and decided, and any result, client or number they gave you), quoted as they said it, and their notes; the fact-check treats these as the author's own account of the work, so a first-hand sentence they don't back is a finding. Never write them yourself: ask the engineer. For a case study: the engineer's own notes and the project's records (README, changelog, metrics they gave you) its numbers come from. Every number in the case study is checked against these; one that isn't here is a finding. A source is not an approval: a client's metric also needs the client register's approval. Ask the engineer for outcome numbers; never invent them. At most 100,000 characters."
},
"markdown": {
"type": "string",
"description": "The whole post: frontmatter (title, description at least) and body. With id: optional, and must be the saved text"
},
"first_hand": {
"type": "array",
"items": {
"type": "object",
"required": [
"claim",
"basis"
],
"properties": {
"basis": {
"enum": [
"measured",
"our_product",
"client_told_us",
"customers_ask",
"we_did_it",
"own_work"
],
"type": "string",
"description": "measured: we measured or ran it; our_product: how our own product works; client_told_us: what a client said (not their numbers); customers_ask: what our customers ask; we_did_it: what we built, saw or decided; own_work: first-hand, from the engineer's own work"
},
"claim": {
"type": "string",
"description": "The sentence, exactly as the fact-check quoted it"
}
},
"additionalProperties": false
},
"maxItems": 10,
"description": "First-hand claims only the engineer can source, which the fact-check flagged first_hand (first_hand_to_confirm): each the sentence exactly as quoted, with what it rests on. Sending it asks the engineer; it never confirms anything on your word. check_draft asks them in their client (an elicitation) where it can, otherwise answers with a question and a one-time confirmation: ask them that question, and only if they say yes, send it back as first_hand_confirmation with the same first_hand. submit_draft and update_draft answer with the question and confirmation too, which come back on check_draft with the id. Never a client's result: a number about a client needs the client's confirmation, as a source."
},
"confirm_via": {
"enum": [
"elicitation",
"token"
],
"type": "string",
"description": "With first_hand or first_hand_all: how the engineer is asked. Default: a form in their client where it can show one. \"token\": the question and a one-time confirmation instead, for a UI that asks them itself (an MCP App's button)"
},
"wait_seconds": {
"type": "integer",
"maximum": 50,
"minimum": 0,
"description": "Without the tasks extension: how long to wait for the result before answering with progress (default and most 25; a larger value, accepted for older agents, waits 25)"
},
"first_hand_all": {
"type": "boolean",
"description": "Confirm all listed: true asks the engineer to confirm, in one go, every first-hand claim the last check of this text listed (first_hand_to_confirm), instead of listing them in first_hand. The list is the server's, from that check: a client's result, a client's fact and a known error are never in it and come back apart (first_hand.excluded). It asks as first_hand does (one form showing every claim, or a question and a one-time confirmation to send back with first_hand_all: true); it never confirms anything on your word. Each claim is still recorded on its own under the engineer's name."
},
"client_confirmed": {
"type": "boolean",
"description": "Only when the engineer tells you they have the client's confirmation to name the client this draft names (its client:, or a client in its text the register doesn't approve). Recorded under the engineer's name with the draft and its text; never send it on your own judgement. It covers naming the client, not results: numbers still need sources."
},
"first_hand_confirmation": {
"type": "string",
"description": "Only after asking the engineer and hearing yes: the confirmation an earlier answer gave for exactly this first_hand (first_hand.confirmation). It works once, for ten minutes, for those claims in that text"
}
},
"additionalProperties": false
}Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). A read, about a millisecond, free: an outline (title options, the opening's two sentences, four to six sections with a line each, the diagram, the FAQ questions; a case study's four sections) against the title, opening-pattern, heading and FAQ rules, before any prose. Fix what it finds and call again until ready; then show the engineer outline_markdown and draft only after their OK.
| Argument | Type | Description |
|---|---|---|
| faqs | array | Three or more questions a reader would search for. Not for a case study. |
| kind | string | |
| reader | string | Who the post is for. |
| titles* | array | Two or three title options, each one clause naming the subject. |
| diagram | string | What the diagram draws, step by step, and its point. Not for a case study. |
| opening | string | The opening's first two sentences: the reader's problem in their words with one concrete detail, then who we are and our first-hand angle. Not for a case study. |
| sections* | array | Four to six for a post; Challenge, Strategy, Solution and Results for a case study. The FAQ isn't one of them. |
Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). Today's topic for a daily post, claimed for you for 24 hours (asking again returns the same one): the topic, angle, target search, sources, internal links, and the brief_id to pass to submit_draft. Status none, with the reason, when there is nothing today: stop there. No model is called. Ask the engineer for first-hand detail; never invent it.
No arguments.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {},
"additionalProperties": false
}Requires a TechFabric engineer's Microsoft sign-in (scope blog.write), and only the site owner's is accepted (the Fabric Agents brief automation runs as him). A read: the briefs proposed and not yet taken, the competitor-gap and backlog searches no post or idea covers yet, the 30 most recent posts and the ideas in flight. What the brief automation reads before it proposes. Deterministic, no model; it changes nothing.
No arguments.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {},
"additionalProperties": false
}One published page of www.techfabric.com as clean Markdown, with its title, search title (metaTitle), description, date, updated, author, tags, FAQs as question and answer pairs, and canonical URL. Takes a URL, a path or a post's slug. Only published, indexable pages. Drafts are private: list_drafts lists a signed-in engineer's drafts; a TechFabric engineer connects with Microsoft (the client's Connect or Authenticate button) to list and write them.
| Argument | Type | Description |
|---|---|---|
| url_or_slug* | string | A techfabric.com URL, a path such as /services/databricks, or a post's slug |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"url_or_slug"
],
"properties": {
"url_or_slug": {
"type": "string",
"maxLength": 500,
"minLength": 1,
"description": "A techfabric.com URL, a path such as /services/databricks, or a post's slug"
}
},
"additionalProperties": false
}Every service, solution, Databricks, AI, cloud, software, accelerator and product page on techfabric.com: its name, URL, kind and summary, exactly as the live page states them. Read one in full with get_page.
No arguments.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {},
"additionalProperties": false
}Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). Where one of your drafts stands (by its id; list_drafts lists them), with next_action: the single next step and the call to make. Also its saved Markdown and base_hash (for update_draft; read them again before each edit, as the engineer may have saved one in the draft app), what is failing, the last check, the preview link and, once published, live_url. If the blog writer is waiting on a fact only the engineer has, it asks them first. Never the editor link: that is in the engineer's email.
| Argument | Type | Description |
|---|---|---|
| id* | string | The idea id |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The idea id"
}
},
"additionalProperties": false
}Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). The site's rule-based checks (slop, claims, known errors, voice, opening, title, description, FAQ, diagram, images, links, a case study's rules) on a post's Markdown, frontmatter included: about a second, free, filing nothing. Iterate with this, never with check_draft: rewrite each passage in rewrite_plan as its fix says and lint again until ready, then review the draft against the judge_rubric it returns. With id, it lints a draft of yours: its saved text, or the markdown you send as an edit to it.
| Argument | Type | Description |
|---|---|---|
| id | string | A draft of yours (the id submit_draft returned). Alone: lints its saved text. With markdown: lints that edit as this draft (its kind, slug, images and sources) before you save it |
| kind | string | What the draft is: "post" (the default, a blog post) or "case-study" (content/case-studies, at /case-studies/<slug>). A case study's frontmatter is title, description, sector, stack, track (ai, migration or other) and client when the client register approves naming them or the engineer says the client agreed (client_confirmed); its body opens with ## Challenge, ## Strategy, ## Solution and ## Results, each with a bold one-line statement first. See the editorial_rules resource. |
| slug | string | The draft's slug, when it has one already (get_status draft.slug); otherwise it comes from the title |
| images | array | The images the post refers to by name (names only; no data needed) |
| rubric |
Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). A read: the site's writing rules and the social rules on a LinkedIn post's text (the AI tells, the slop, claims, announcement openers, engagement bait, hashtags), its length, what shows before "see more", and, with post, whether it links the post. Rewrite each finding and lint again until ready. Posts nothing.
| Argument | Type | Description |
|---|---|---|
| post | string | The published post it shares (its URL or slug): the text is checked for its link |
| text* | string | The LinkedIn post's text, as the engineer would post it (at most 10000 characters) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"text"
],
"properties": {
"post": {
"type": "string",
"description": "The published post it shares (its URL or slug): the text is checked for its link"
},
"text": {
"type": "string",
"description": "The LinkedIn post's text, as the engineer would post it (at most 10000 characters)"
}
},
"additionalProperties": false
}Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). Lists your drafts (blog posts, case studies and revisions of live posts), newest first: each one's id, title, kind, state (writing, question_for_you, drafted, checks_failing, ready_to_publish, published and the rest), created and updated dates, preview link and next_action. Filter by state, kind and creation date (created_after, created_before: "yesterday" is the day before the answer's today), and page with cursor. The editor may pass all for everyone's; the site owner, stale: true for his owner queue (drafts stuck over two days). Reads only. Then get_status with an id for one draft in detail.
| Argument | Type | Description |
|---|---|---|
| all | boolean | The blog's editor only: everyone's drafts, not just yours. Refused for anyone else |
| kind | string | Only this kind: post, case-study, or revision (of a live post). Leave it out for all |
| limit | integer | How many to return, newest first (default 20) |
| stale | boolean | The site owner only, his owner queue: everyone's drafts with nothing from their author for more than two days (stuck, a question for them, held, drafted or failing checks; never an agent's explainer), oldest wait first. "Show my owner queue" is this. Refused for anyone else |
| state | string | Only drafts in this state: writing, preview_building, question_for_you, drafted, checking, checks_failing, ready_to_publish, publishing, published, stuck, closed; or open, every one not yet published or closed; or stale, the site owner's queue (as stale: true). Leave it out for all |
TechFabric's published blog posts, newest first, optionally only those with a tag, by an author, or dated on or after a day. Drafts are private: list_drafts lists a signed-in engineer's drafts; a TechFabric engineer connects with Microsoft (the client's Connect or Authenticate button) to list and write them.
| Argument | Type | Description |
|---|---|---|
| tag | string | Only posts with this tag (its name or slug, e.g. Databricks) |
| limit | integer | How many posts (default 20) |
| since | string | Only posts dated on or after this day, YYYY-MM-DD |
| author | string | Only posts by this author (name or slug, e.g. Preetham Reddy) |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"tag": {
"type": "string",
"description": "Only posts with this tag (its name or slug, e.g. Databricks)"
},
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "How many posts (default 20)"
},
"since": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Only posts dated on or after this day, YYYY-MM-DD"
},
"author": {
"type": "string",
"description": "Only posts by this author (name or slug, e.g. Preetham Reddy)"
}
},
"additionalProperties": false
}Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). A read: how one of your own published posts is doing in Google (the blog's editor: any post). Search Console's clicks, impressions, CTR and average position for the last 28 days against the 28 before, the searches it shows for, whether Google has indexed it, and what to improve, each with the numbers behind it. Without post: all your posts with their last 28 days. Searches from the US only, so totals are lower than Search Console's all-countries view; cached for six hours. No model is called and nothing changes: revise_post changes a live post, only after the engineer agrees.
| Argument | Type | Description |
|---|---|---|
| post | string | One of your published posts: its URL (https://www.techfabric.com/blog/<slug>) or its slug. Leave it out for all your posts, with their last 28 days. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"post": {
"type": "string",
"description": "One of your published posts: its URL (https://www.techfabric.com/blog/<slug>) or its slug. Leave it out for all your posts, with their last 28 days."
}
},
"additionalProperties": false
}Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). A read: every ```mermaid block in a post (or one mermaid source), as the site will treat it. For each: its lines in the post, its caption, whether the site's mermaid parses it (with the error and its line in the post when it doesn't), and the diagram rules' findings (a caption that states the point; no fact in a label the section's text doesn't say). In a host that renders MCP Apps it opens the diagrams drawn in the site's theme. Files nothing, calls no model; use it while drafting, then lint_draft the whole post.
| Argument | Type | Description |
|---|---|---|
| markdown* | string | The whole post, frontmatter included, or one mermaid source. At most 200,000 characters |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"markdown"
],
"properties": {
"markdown": {
"type": "string",
"description": "The whole post, frontmatter included, or one mermaid source. At most 200,000 characters"
}
},
"additionalProperties": false
}Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). A read: one of your drafts as techfabric.com renders it, with its last checks (each marked as one the engineer may publish past or one that must pass) and whether Publish may run, for the draft app in a host that shows MCP Apps. In any host its text starts with the preview link: show it to the engineer.
| Argument | Type | Description |
|---|---|---|
| id* | string | The idea id |
| editing | boolean | The draft app only, never an agent: true while the engineer has unsaved edits in its Edit tab (takes or renews the app's edit hold), false when they save, discard or leave it (lets go). It changes no text; with it the answer is the hold, not the preview |
| instance | string | The draft app only: its view's own id, with editing |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The idea id"
},
"editing": {
"type": "boolean",
"description": "The draft app only, never an agent: true while the engineer has unsaved edits in its Edit tab (takes or renews the app's edit hold), false when they save, discard or leave it (lets go). It changes no text; with it the answer is the hold, not the preview"
},
"instance": {
"type": "string",
"description": "The draft app only: its view's own id, with editing"
}
},
"additionalProperties": false
}Requires a TechFabric engineer's Microsoft sign-in (scope blog.write), and only the site owner's is accepted (the Fabric Agents brief automation runs as him). Adds one brief to the pool get_brief offers engineers, first and matched to their work: topic, why (the evidence), angle, sources, target_query, for_author. Refused with the reason, nothing stored, when a live post or an idea in flight covers it, an open proposal already is it, or today's 3 are used; the same topic again is the same brief. Drafts and publishes nothing; no model.
| Argument | Type | Description |
|---|---|---|
| why* | string | The evidence: the TechFabric work it comes from (a repository, a project, a published post), or the search data (query, monthly volume, who ranks). Never a guess |
| angle* | string | What the post argues or shows, and for which reader |
| topic* | string | The post's subject in a few words (8 to 140 characters) |
| sources | array | |
| for_author | string | An engineer from the author registry, when the work is theirs; leave out to offer it to whoever's work fits |
| target_query | string | The search the post should answer, when there is one |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"topic",
"why",
"angle"
],
"properties": {
"why": {
"type": "string",
"description": "The evidence: the TechFabric work it comes from (a repository, a project, a published post), or the search data (query, monthly volume, who ranks). Never a guess"
},
"angle": {
"type": "string",
"description": "What the post argues or shows, and for which reader"
},
"topic": {
"type": "string",
"description": "The post's subject in a few words (8 to 140 characters)"
},
"sources": {
"type": "array",
"items": {
"type": "object",
"required": [
"title",
"url"
],
"properties": {
"url": {
"type": "string",
"description": "https URL"
},
"title": {
"type": "string"
}
},
"additionalProperties": false
},
"maxItems": 5
},
"for_author": {
"type": "string",
"description": "An engineer from the author registry, when the work is theirs; leave out to offer it to whoever's work fits"
},
"target_query": {
"type": "string",
"description": "The search the post should answer, when there is one"
}
},
"additionalProperties": false
}Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). Publish one of your drafts to techfabric.com, only after the engineer confirms, once check_draft with the id has passed on exactly the saved text. The first call publishes nothing: it asks the engineer by a form in their client, or returns a one-time confirmation that you send back on a second call only after their yes. Never in a scheduled or unattended run. override names wording checks the engineer chooses to publish past (never the hard set, the fact-check, slop, quality, opening or ending). confirm_via "token": always return the one-time confirmation instead of a form, for a UI that asks the engineer itself.
| Argument | Type | Description |
|---|---|---|
| id* | string | The idea id of your own draft |
| override | array | Publish anyway: the failing check ids (as check_draft reports them, such as gate:buyer) the engineer chooses to publish past. Only wording and style checks; the hard set (the page working, claims, our own spend, secrets) always has to pass. Send the same list on the confirming call |
| confirm_via | string | How the engineer is asked. Default: elicitation where the client supports it. "token": the first call returns a one-time confirmation instead, for a UI (an MCP App's Publish button) that asks the engineer itself |
| confirmation | string | Only on the second call: the confirmation the first call returned, sent back after the engineer said yes |
Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). A read: what your agent needs to draft a Reddit post or thread answer in your own voice, from a published techfabric.com post or your own notes. The subreddit's rules, the frame (a plain title; first person; the problem, what you tried, what worked, your numbers), the disclosure line, the optional link last, a checklist and the steps to post it yourself. Send draft to check it: the site's writing rules plus Reddit's (no hashtags, no 'check out our', no call to action, substance before any link). No model is called and nothing is posted, voted or commented.
| Argument | Type | Description |
|---|---|---|
| post | string | A published post on techfabric.com the Reddit post draws on: its URL or its slug. Optional |
| draft | object | The draft to check: the result then carries lint. Send it again after each rewrite until lint.ready is true |
| notes | string | The engineer's own notes about the problem, what they tried, what worked and their numbers (at most 8000 characters). Optional; send post, notes or both |
| thread | string | The Reddit thread being answered, if this is an answer: its URL. Optional |
| subreddit* | string | The subreddit the post or answer is for |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"subreddit"
],
"properties": {
"post": {
"type": "string",
"description": "A published post on techfabric.com the Reddit post draws on: its URL or its slug. Optional"
},
"draft": {
"type": "object",
"required": [
"body"
],
"properties": {
"body": {
"type": "string",
"description": "The post's body, as the engineer would paste it"
},
"title": {
"type": "string",
"description": "The post's title (for an answer in a thread, leave it empty)"
}
},
"description": "The draft to check: the result then carries lint. Send it again after each rewrite until lint.ready is true",
"additionalProperties": false
},
"notes": {
"type": "string",
"description": "The engineer's own notes about the problem, what they tried, what worked and their numbers (at most 8000 characters). Optional; send post, notes or both"
},
"thread": {
"type": "string",
"description": "The Reddit thread being answered, if this is an answer: its URL. Optional"
},
"subreddit": {
"enum": [
"databricks",
"dataengineering",
"MicrosoftFabric",
"AZURE"
],
"type": "string",
"description": "The subreddit the post or answer is for"
}
},
"additionalProperties": false
}Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). A read: whether one of your drafts may be published now, and if so the question to ask the engineer ("Publish '<title>' now? (yes/no)") with a one-time confirmation for this exact saved text and its checks (used once). Only after they say yes, call publish_draft with the id and that confirmation, and the same override. If it can't be published yet, it says why and what to do.
| Argument | Type | Description |
|---|---|---|
| id* | string | The idea id of your own draft |
| override | array | Publish anyway: the failing check ids the engineer chooses to publish past (only wording and style checks). Send the same list to publish_draft with the confirmation |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The idea id of your own draft"
},
"override": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 20,
"description": "Publish anyway: the failing check ids the engineer chooses to publish past (only wording and style checks). Send the same list to publish_draft with the confirmation"
}
},
"additionalProperties": false
}Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). Open a revision of a post that is live on techfabric.com, by its URL or slug: only its author or the blog's editor. The revision's draft starts as the live text, with its own preview; then the same loop: get_status for its markdown, lint_draft with the id and your edit, update_draft, check_draft with the id, publish_draft. Publishing replaces the post at the same URL and byline and keeps its date. Asking again returns the revision already open.
| Argument | Type | Description |
|---|---|---|
| post* | string | The live post to change: its URL (https://www.techfabric.com/blog/<slug>) or its slug |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"post"
],
"properties": {
"post": {
"type": "string",
"description": "The live post to change: its URL (https://www.techfabric.com/blog/<slug>) or its slug"
}
},
"additionalProperties": false
}Search TechFabric's published site: blog posts, service and solution pages, case studies, city pages and events. Returns each match's title, URL, summary, date, author and type, best first. Read a result in full with get_page. Drafts are private: list_drafts lists a signed-in engineer's drafts; a TechFabric engineer connects with Microsoft (the client's Connect or Authenticate button) to list and write them.
| Argument | Type | Description |
|---|---|---|
| type | string | Only this kind of page: post, service, solution, case_study, city, event or page |
| limit | integer | How many results (default 10) |
| query* | string | What to look for, in plain words |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"query"
],
"properties": {
"type": {
"enum": [
"post",
"service",
"solution",
"case_study",
"city",
"event",
"page"
],
"type": "string",
"description": "Only this kind of page: post, service, solution, case_study, city, event or page"
},
"limit": {
"type": "integer",
"maximum": 25,
"minimum": 1,
"description": "How many results (default 10)"
},
"query": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "What to look for, in plain words"
}
},
"additionalProperties": false
}Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). A read: what your agent needs to draft a LinkedIn post about a published techfabric.com post, any post on the site. Its key points and first-hand sentences, its link with the LinkedIn campaign, the engineer's voice notes, the social rules and LinkedIn's lengths. No model is called and nothing is posted: draft the post from it, check it with lint_social, and show the engineer the text to post themselves.
| Argument | Type | Description |
|---|---|---|
| post* | string | A published post on techfabric.com: its URL (https://www.techfabric.com/blog/<slug>) or its slug |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"post"
],
"properties": {
"post": {
"type": "string",
"description": "A published post on techfabric.com: its URL (https://www.techfabric.com/blog/<slug>) or its slug"
}
},
"additionalProperties": false
}Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). Start here, before writing anything: the interview for a post, a case study or an explainer, about seven questions tailored to the topic and to today's brief. Send suggested (your answers from the repository) so the engineer only confirms or corrects. A client that answers forms shows them as one form; otherwise ask them in chat and call again with answers. Returns their answers as sources for submit_draft, then outline and check_outline before any prose. A read: nothing is filed or claimed.
| Argument | Type | Description |
|---|---|---|
| form | boolean | false: never show the form; return the questions to ask in chat. |
| kind | string | What the engineer is writing: "post" (the default), "case-study", or "explainer" (a post on news or a feature; submit it as kind "post"). |
| brief | boolean | Tailor the questions to the brief the engineer holds today (get_brief claims one; this only reads it). |
| topic | string | What it is about, in the engineer's words. Leave it out with brief: true. |
| answers | object | The engineer's own answers, by question id, word for word, once they've given them in chat: returned as sources for submit_draft. |
| suggested | object | Your suggested answer to each question, by its id, from the repository and the engineer's notes: shown to them to confirm or correct, never sent as their words. |
Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). File a post (or, with kind "case-study", a case study) under the engineer's byline, exactly as written: the site builds its preview and emails it to them. Send the whole Markdown with frontmatter (title and description at least), the engineer's own words as sources, and brief_id when it comes from get_brief. Lint it clean first. Returns the draft's id and text_hash; next, check_draft with the id. Never publishes.
| Argument | Type | Description |
|---|---|---|
| kind | string | What the draft is: "post" (the default, a blog post) or "case-study" (content/case-studies, at /case-studies/<slug>). A case study's frontmatter is title, description, sector, stack, track (ai, migration or other) and client when the client register approves naming them or the engineer says the client agreed (client_confirmed); its body opens with ## Challenge, ## Strategy, ## Solution and ## Results, each with a bold one-line statement first. See the editorial_rules resource. |
| title* | string | The post's working title |
| images | array | |
| sources | string | The engineer's own words the draft's claims come from, as text. For a post: what the engineer told you about their own work (what they built, measured, saw and decided, and any result, client or number they gave you), quoted as they said it, and their notes; the fact-check treats these as the author's own account of the work, so a first-hand sentence they don't back is a finding. Never write them yourself: ask the engineer. For a case study: the engineer's own notes and the project's records (README, changelog, metrics they gave you) its numbers come from. Every number in the case study is checked against these; one that isn't here is a finding. A source is not an approval: a client's metric also needs the client register's approval. Ask the engineer for outcome numbers; never invent them. At most 100,000 characters. |
Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). A read: the pages of ours a draft or post should link (posts, services, solutions and case studies sharing its distinctive words), each with why and where (the section, the paragraph and a phrase for the anchor), never one it already links; and the open searches that match your own work: searches people make that competitors rank for, or that we target, and that no post of ours answers yet. Send markdown, id (one of your drafts) or post (one of your published posts); nothing at all for topics only. Deterministic, no model; it changes nothing.
| Argument | Type | Description |
|---|---|---|
| id | string | One of your drafts (the id submit_draft returned): its saved text |
| post | string | One of your published posts: its URL (https://www.techfabric.com/blog/<slug>) or its slug |
| markdown | string | The post's text, frontmatter included. With id: an edit of that draft, read instead of its saved text |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [],
"properties": {
"id": {
"type": "string",
"description": "One of your drafts (the id submit_draft returned): its saved text"
},
"post": {
"type": "string",
"description": "One of your published posts: its URL (https://www.techfabric.com/blog/<slug>) or its slug"
},
"markdown": {
"type": "string",
"description": "The post's text, frontmatter included. With id: an edit of that draft, read instead of its saved text"
}
},
"additionalProperties": false
}Requires a TechFabric engineer's Microsoft sign-in (scope blog.write). Save a new version of your draft (state drafted): the whole Markdown, and base_hash, the hash of the version you edited (draft.base_hash from get_status, or your last update_draft's text_hash). Answers in a second or two; the preview rebuilds in the background. It runs no checks: lint_draft the edit first, then check_draft with the id. Refused if the draft changed since base_hash or is open in the browser editor. The engineer may also edit and save it in the draft app: start each edit from a fresh get_status. Never publishes.
| Argument | Type | Description |
|---|---|---|
| id* | string | The idea id |
| kind | string | Optional: the draft's kind, which is fixed when it is submitted. Sent, it must match (get_status says it). |
| sources | string | New sources, replacing the ones sent before: the engineer's own words, which the fact-check reads a post's claims against, or a case study's numbers are checked against. |
| base_sha | string | Instead of base_hash: draft.base_sha from get_status, the commit your edit started from |
| markdown* | string | The whole post, with its frontmatter |
| base_hash | string | The hash of the version your edit started from: draft.base_hash from the get_status you edited from, or the text_hash your last update_draft returned. It stays good after that save is committed |
| meta_title | string | A search title of 60 characters or fewer, only when a title runs longer. |
| unattended | boolean | true in a scheduled run with nobody to approve the outline: a passing outline goes straight to drafting. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"titles",
"sections"
],
"properties": {
"faqs": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 12,
"description": "Three or more questions a reader would search for. Not for a case study."
},
"kind": {
"enum": [
"post",
"case-study",
"explainer"
],
"type": "string",
"default": "post"
},
"reader": {
"type": "string",
"description": "Who the post is for."
},
"titles": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 5,
"description": "Two or three title options, each one clause naming the subject."
},
"diagram": {
"type": "string",
"description": "What the diagram draws, step by step, and its point. Not for a case study."
},
"opening": {
"type": "string",
"description": "The opening's first two sentences: the reader's problem in their words with one concrete detail, then who we are and our first-hand angle. Not for a case study."
},
"sections": {
"type": "array",
"items": {
"type": "object",
"required": [
"heading"
],
"properties": {
"heading": {
"type": "string"
},
"summary": {
"type": "string",
"description": "One line: what the section tells the reader"
}
}
},
"maxItems": 12,
"description": "Four to six for a post; Challenge, Strategy, Solution and Results for a case study. The FAQ isn't one of them."
},
"meta_title": {
"type": "string",
"description": "A search title of 60 characters or fewer, only when a title runs longer."
},
"unattended": {
"type": "boolean",
"description": "true in a scheduled run with nobody to approve the outline: a passing outline goes straight to drafting."
}
},
"additionalProperties": false
}| boolean |
| Also return judge_rubric while checks still fail (it comes anyway once they pass) |
| sources | string | The engineer's own words the draft's claims come from, as text. For a post: what the engineer told you about their own work (what they built, measured, saw and decided, and any result, client or number they gave you), quoted as they said it, and their notes; the fact-check treats these as the author's own account of the work, so a first-hand sentence they don't back is a finding. Never write them yourself: ask the engineer. For a case study: the engineer's own notes and the project's records (README, changelog, metrics they gave you) its numbers come from. Every number in the case study is checked against these; one that isn't here is a finding. A source is not an approval: a client's metric also needs the client register's approval. Ask the engineer for outcome numbers; never invent them. At most 100,000 characters. |
| markdown | string | The whole post: frontmatter (title, description at least) and body |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [],
"properties": {
"id": {
"type": "string",
"description": "A draft of yours (the id submit_draft returned). Alone: lints its saved text. With markdown: lints that edit as this draft (its kind, slug, images and sources) before you save it"
},
"kind": {
"enum": [
"post",
"case-study"
],
"type": "string",
"default": "post",
"description": "What the draft is: \"post\" (the default, a blog post) or \"case-study\" (content/case-studies, at /case-studies/<slug>). A case study's frontmatter is title, description, sector, stack, track (ai, migration or other) and client when the client register approves naming them or the engineer says the client agreed (client_confirmed); its body opens with ## Challenge, ## Strategy, ## Solution and ## Results, each with a bold one-line statement first. See the editorial_rules resource."
},
"slug": {
"type": "string",
"description": "The draft's slug, when it has one already (get_status draft.slug); otherwise it comes from the title"
},
"images": {
"type": "array",
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"alt": {
"type": "string",
"description": "What the image shows, for its alt text and caption"
},
"data": {
"type": "string",
"description": "The image's bytes, base64 (PNG, JPEG, WebP or GIF, at most 10 MB). Required by submit_draft; check_draft needs only the name."
},
"name": {
"type": "string",
"description": "The file name the post refers to the image by, e.g. pipeline.png"
}
},
"additionalProperties": false
},
"maxItems": 10,
"description": "The images the post refers to by name (names only; no data needed)"
},
"rubric": {
"type": "boolean",
"description": "Also return judge_rubric while checks still fail (it comes anyway once they pass)"
},
"sources": {
"type": "string",
"description": "The engineer's own words the draft's claims come from, as text. For a post: what the engineer told you about their own work (what they built, measured, saw and decided, and any result, client or number they gave you), quoted as they said it, and their notes; the fact-check treats these as the author's own account of the work, so a first-hand sentence they don't back is a finding. Never write them yourself: ask the engineer. For a case study: the engineer's own notes and the project's records (README, changelog, metrics they gave you) its numbers come from. Every number in the case study is checked against these; one that isn't here is a finding. A source is not an approval: a client's metric also needs the client register's approval. Ask the engineer for outcome numbers; never invent them. At most 100,000 characters."
},
"markdown": {
"type": "string",
"description": "The whole post: frontmatter (title, description at least) and body"
}
},
"additionalProperties": false
}| cursor | string | The next_cursor from the previous page, with the same filters |
| created_after | string | Only drafts created at or after this: a date (YYYY-MM-DD, midnight UTC) or an ISO 8601 time with its offset. For yesterday: created_after yesterday's date and created_before today's (the answer's today is the server's date, UTC; pass times with the engineer's offset for their own day) |
| created_before | string | Only drafts created before this (not at it): a date (YYYY-MM-DD, midnight UTC) or an ISO 8601 time |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"all": {
"type": "boolean",
"description": "The blog's editor only: everyone's drafts, not just yours. Refused for anyone else"
},
"kind": {
"enum": [
"post",
"case-study",
"revision"
],
"type": "string",
"description": "Only this kind: post, case-study, or revision (of a live post). Leave it out for all"
},
"limit": {
"type": "integer",
"maximum": 50,
"minimum": 1,
"description": "How many to return, newest first (default 20)"
},
"stale": {
"type": "boolean",
"description": "The site owner only, his owner queue: everyone's drafts with nothing from their author for more than two days (stuck, a question for them, held, drafted or failing checks; never an agent's explainer), oldest wait first. \"Show my owner queue\" is this. Refused for anyone else"
},
"state": {
"enum": [
"writing",
"preview_building",
"question_for_you",
"drafted",
"checking",
"checks_failing",
"ready_to_publish",
"publishing",
"published",
"stuck",
"closed",
"open",
"stale"
],
"type": "string",
"description": "Only drafts in this state: writing, preview_building, question_for_you, drafted, checking, checks_failing, ready_to_publish, publishing, published, stuck, closed; or open, every one not yet published or closed; or stale, the site owner's queue (as stale: true). Leave it out for all"
},
"cursor": {
"type": "string",
"description": "The next_cursor from the previous page, with the same filters"
},
"created_after": {
"type": "string",
"description": "Only drafts created at or after this: a date (YYYY-MM-DD, midnight UTC) or an ISO 8601 time with its offset. For yesterday: created_after yesterday's date and created_before today's (the answer's today is the server's date, UTC; pass times with the engineer's offset for their own day)"
},
"created_before": {
"type": "string",
"description": "Only drafts created before this (not at it): a date (YYYY-MM-DD, midnight UTC) or an ISO 8601 time"
}
},
"additionalProperties": false
}{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"description": "The idea id of your own draft"
},
"override": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 20,
"description": "Publish anyway: the failing check ids (as check_draft reports them, such as gate:buyer) the engineer chooses to publish past. Only wording and style checks; the hard set (the page working, claims, our own spend, secrets) always has to pass. Send the same list on the confirming call"
},
"confirm_via": {
"enum": [
"elicitation",
"token"
],
"type": "string",
"description": "How the engineer is asked. Default: elicitation where the client supports it. \"token\": the first call returns a one-time confirmation instead, for a UI (an MCP App's Publish button) that asks the engineer itself"
},
"confirmation": {
"type": "string",
"description": "Only on the second call: the confirmation the first call returned, sent back after the engineer said yes"
}
},
"additionalProperties": false
}{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"form": {
"type": "boolean",
"default": true,
"description": "false: never show the form; return the questions to ask in chat."
},
"kind": {
"enum": [
"post",
"case-study",
"explainer"
],
"type": "string",
"default": "post",
"description": "What the engineer is writing: \"post\" (the default), \"case-study\", or \"explainer\" (a post on news or a feature; submit it as kind \"post\")."
},
"brief": {
"type": "boolean",
"description": "Tailor the questions to the brief the engineer holds today (get_brief claims one; this only reads it)."
},
"topic": {
"type": "string",
"description": "What it is about, in the engineer's words. Leave it out with brief: true."
},
"answers": {
"type": "object",
"description": "The engineer's own answers, by question id, word for word, once they've given them in chat: returned as sources for submit_draft.",
"additionalProperties": {
"type": "string",
"maxLength": 12000
}
},
"suggested": {
"type": "object",
"description": "Your suggested answer to each question, by its id, from the repository and the engineer's notes: shown to them to confirm or correct, never sent as their words.",
"additionalProperties": {
"type": "string",
"maxLength": 12000
}
}
},
"additionalProperties": false
}| brief_id | string | The brief_id get_brief returned, when the post is from today's brief: it marks the brief done |
| markdown* | string | The whole post, with its frontmatter (title, description at least): it becomes the draft as sent |
| first_hand | array | First-hand claims only the engineer can source, which the fact-check flagged first_hand (first_hand_to_confirm): each the sentence exactly as quoted, with what it rests on. Sending it asks the engineer; it never confirms anything on your word. check_draft asks them in their client (an elicitation) where it can, otherwise answers with a question and a one-time confirmation: ask them that question, and only if they say yes, send it back as first_hand_confirmation with the same first_hand. submit_draft and update_draft answer with the question and confirmation too, which come back on check_draft with the id. Never a client's result: a number about a client needs the client's confirmation, as a source. |
| client_confirmed | boolean | Only when the engineer tells you they have the client's confirmation to name the client this draft names (its client:, or a client in its text the register doesn't approve). Recorded under the engineer's name with the draft and its text; never send it on your own judgement. It covers naming the client, not results: numbers still need sources. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"title",
"markdown"
],
"properties": {
"kind": {
"enum": [
"post",
"case-study"
],
"type": "string",
"default": "post",
"description": "What the draft is: \"post\" (the default, a blog post) or \"case-study\" (content/case-studies, at /case-studies/<slug>). A case study's frontmatter is title, description, sector, stack, track (ai, migration or other) and client when the client register approves naming them or the engineer says the client agreed (client_confirmed); its body opens with ## Challenge, ## Strategy, ## Solution and ## Results, each with a bold one-line statement first. See the editorial_rules resource."
},
"title": {
"type": "string",
"description": "The post's working title"
},
"images": {
"type": "array",
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"alt": {
"type": "string",
"description": "What the image shows, for its alt text and caption"
},
"data": {
"type": "string",
"description": "The image's bytes, base64 (PNG, JPEG, WebP or GIF, at most 10 MB). Required by submit_draft; check_draft needs only the name."
},
"name": {
"type": "string",
"description": "The file name the post refers to the image by, e.g. pipeline.png"
}
},
"additionalProperties": false
},
"maxItems": 10
},
"sources": {
"type": "string",
"description": "The engineer's own words the draft's claims come from, as text. For a post: what the engineer told you about their own work (what they built, measured, saw and decided, and any result, client or number they gave you), quoted as they said it, and their notes; the fact-check treats these as the author's own account of the work, so a first-hand sentence they don't back is a finding. Never write them yourself: ask the engineer. For a case study: the engineer's own notes and the project's records (README, changelog, metrics they gave you) its numbers come from. Every number in the case study is checked against these; one that isn't here is a finding. A source is not an approval: a client's metric also needs the client register's approval. Ask the engineer for outcome numbers; never invent them. At most 100,000 characters."
},
"brief_id": {
"type": "string",
"description": "The brief_id get_brief returned, when the post is from today's brief: it marks the brief done"
},
"markdown": {
"type": "string",
"description": "The whole post, with its frontmatter (title, description at least): it becomes the draft as sent"
},
"first_hand": {
"type": "array",
"items": {
"type": "object",
"required": [
"claim",
"basis"
],
"properties": {
"basis": {
"enum": [
"measured",
"our_product",
"client_told_us",
"customers_ask",
"we_did_it",
"own_work"
],
"type": "string",
"description": "measured: we measured or ran it; our_product: how our own product works; client_told_us: what a client said (not their numbers); customers_ask: what our customers ask; we_did_it: what we built, saw or decided; own_work: first-hand, from the engineer's own work"
},
"claim": {
"type": "string",
"description": "The sentence, exactly as the fact-check quoted it"
}
},
"additionalProperties": false
},
"maxItems": 10,
"description": "First-hand claims only the engineer can source, which the fact-check flagged first_hand (first_hand_to_confirm): each the sentence exactly as quoted, with what it rests on. Sending it asks the engineer; it never confirms anything on your word. check_draft asks them in their client (an elicitation) where it can, otherwise answers with a question and a one-time confirmation: ask them that question, and only if they say yes, send it back as first_hand_confirmation with the same first_hand. submit_draft and update_draft answer with the question and confirmation too, which come back on check_draft with the id. Never a client's result: a number about a client needs the client's confirmation, as a source."
},
"client_confirmed": {
"type": "boolean",
"description": "Only when the engineer tells you they have the client's confirmation to name the client this draft names (its client:, or a client in its text the register doesn't approve). Recorded under the engineer's name with the draft and its text; never send it on your own judgement. It covers naming the client, not results: numbers still need sources."
}
},
"additionalProperties": false
}| first_hand | array | First-hand claims only the engineer can source, which the fact-check flagged first_hand (first_hand_to_confirm): each the sentence exactly as quoted, with what it rests on. Sending it asks the engineer; it never confirms anything on your word. check_draft asks them in their client (an elicitation) where it can, otherwise answers with a question and a one-time confirmation: ask them that question, and only if they say yes, send it back as first_hand_confirmation with the same first_hand. submit_draft and update_draft answer with the question and confirmation too, which come back on check_draft with the id. Never a client's result: a number about a client needs the client's confirmation, as a source. |
| app_instance | string | The draft app only, never an agent: the view whose own unsaved edits this save is |
| client_confirmed | boolean | Only when the engineer tells you they have the client's confirmation to name the client this draft names (its client:, or a client in its text the register doesn't approve). Recorded under the engineer's name with the draft and its text; never send it on your own judgement. It covers naming the client, not results: numbers still need sources. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"markdown"
],
"properties": {
"id": {
"type": "string",
"description": "The idea id"
},
"kind": {
"enum": [
"post",
"case-study"
],
"type": "string",
"default": "post",
"description": "Optional: the draft's kind, which is fixed when it is submitted. Sent, it must match (get_status says it)."
},
"sources": {
"type": "string",
"description": "New sources, replacing the ones sent before: the engineer's own words, which the fact-check reads a post's claims against, or a case study's numbers are checked against."
},
"base_sha": {
"type": "string",
"description": "Instead of base_hash: draft.base_sha from get_status, the commit your edit started from"
},
"markdown": {
"type": "string",
"description": "The whole post, with its frontmatter"
},
"base_hash": {
"type": "string",
"description": "The hash of the version your edit started from: draft.base_hash from the get_status you edited from, or the text_hash your last update_draft returned. It stays good after that save is committed"
},
"first_hand": {
"type": "array",
"items": {
"type": "object",
"required": [
"claim",
"basis"
],
"properties": {
"basis": {
"enum": [
"measured",
"our_product",
"client_told_us",
"customers_ask",
"we_did_it",
"own_work"
],
"type": "string",
"description": "measured: we measured or ran it; our_product: how our own product works; client_told_us: what a client said (not their numbers); customers_ask: what our customers ask; we_did_it: what we built, saw or decided; own_work: first-hand, from the engineer's own work"
},
"claim": {
"type": "string",
"description": "The sentence, exactly as the fact-check quoted it"
}
},
"additionalProperties": false
},
"maxItems": 10,
"description": "First-hand claims only the engineer can source, which the fact-check flagged first_hand (first_hand_to_confirm): each the sentence exactly as quoted, with what it rests on. Sending it asks the engineer; it never confirms anything on your word. check_draft asks them in their client (an elicitation) where it can, otherwise answers with a question and a one-time confirmation: ask them that question, and only if they say yes, send it back as first_hand_confirmation with the same first_hand. submit_draft and update_draft answer with the question and confirmation too, which come back on check_draft with the id. Never a client's result: a number about a client needs the client's confirmation, as a source."
},
"app_instance": {
"type": "string",
"description": "The draft app only, never an agent: the view whose own unsaved edits this save is"
},
"client_confirmed": {
"type": "boolean",
"description": "Only when the engineer tells you they have the client's confirmation to name the client this draft names (its client:, or a client in its text the register doesn't approve). Recorded under the engineer's name with the draft and its text; never send it on your own judgement. It covers naming the client, not results: numbers still need sources."
}
},
"additionalProperties": false
}