Date: 2026-01-30
In the Typefully Raycast extension, Raycast AI sometimes calls the create-draft tool without content or prompt, even though the model just produced draft text in its chat response. The tool receives {} and fails, or the API rejects invalid/empty fields like schedule_date: "". This makes the AI workflow unreliable and forces retries.
We added guardrails and examples, but the issue persists intermittently; the model still sometimes omits required arguments.
- Raycast AI chat (model shown in UI: GPT-4o)
- Typefully Raycast extension
- Tool name:
create-draft
- In Raycast AI, run a prompt like:
- "@typefully create a small draft with a joke about vibecoding"
- The assistant replies with a joke.
- The tool call logs show the tool called with empty args.
Tool call log (example):
create-draft tool called with:
{}
Error: Content is required. Provide draft text or a prompt to generate it.
In another case, the tool was called with an empty schedule date:
create-draft tool called with:
{
"title": "",
"prompt": "",
"schedule_date": "",
"content": "<draft text>",
"platforms": [],
"tags": []
}
Error: Some fields are invalid.: Input should be a valid datetime or date, input is too short, Input should be 'now' or 'next-free-slot'
Sometimes the AI retries and succeeds on a second call, but not consistently.
When the assistant generates draft text, it should pass either:
contentwith the full draft text, orprompt(if it wants the tool to generate the draft)
Also, optional fields like schedule_date should be omitted when empty.
We updated tool instructions, added eval examples, and hardened the tool to ignore empty schedule_date, but the model still occasionally sends {} or empty fields. This appears to be a Raycast AI tool-calling reliability issue rather than tool validation.
Tool input + content resolution (Raycast tool receives input from AI):
type Input = {
content?: string;
prompt?: string;
platforms?: string[];
title?: string;
schedule_date?: string;
tags?: string[];
};
async function resolveContent(input: Input) {
const content = input.content?.trim();
if (content) return content;
const prompt = input.prompt?.trim();
if (!prompt) return "";
const aiPrompt = [
"Write a social media draft for Typefully.",
"Return ONLY the draft text. Do not add quotes or commentary.",
"If the request is for a thread, separate posts with a line containing only ---.",
`User request: ${prompt}`,
].join("\\n");
return (await AI.ask(aiPrompt, { creativity: "medium" })).trim();
}Tool execution (fails if tool is called with {}):
export default async function tool(input: Input) {
const content = await resolveContent(input);
if (!content) {
throw new Error("Content is required. Provide draft text or a prompt to generate it.");
}
const scheduleDate = input.schedule_date?.trim();
// ...
const draft = await createDraft(socialSetId, {
platforms,
draft_title: input.title ?? undefined,
tags: input.tags?.length ? input.tags : undefined,
publish_at: scheduleDate || undefined,
});
}AI instructions snippet (extension package.json):
"ai": {
"instructions": "When creating a draft, always call create-draft; if you have exact draft text, pass it in content, otherwise pass the idea in prompt and let the tool generate the draft."
}