GenAI
GenAI is lk-wiz's Bedrock-backed writing assistant. It drafts a post from an idea, rewrites existing content on instruction, and proofreads a draft for grammar and LinkedIn fit. It has no lifecycle of its own — every call is stateless request/response; nothing is queued, scheduled, or tracked by this domain.
This page describes the product-facing behavior. For exact request/response
shapes and error codes, see the GenAI API reference.
For programmatic access from an AI client, see GenAI MCP tools
— and note that the MCP tools behave differently from the HTTP API in
important ways (see MCP vs. HTTP API). The underlying
spec this page is based on is specs/features/genai.md in the repo.
At a glance
| Capability | Endpoint | Persists? |
|---|---|---|
| Generate | POST /api/genai/generate | No — returns text only |
| Iterate | POST /api/genai/iterate | No — returns a suggestion only |
| Proofread | POST /api/genai/proofread | No — returns annotations only |
Every call requires the caller to be a member of the target workspace (any
role — there's no extra gate for viewers here), and every call is timed
and counted via CloudWatch metrics (GenAIGeneration, GenAILatencyMs,
tagged by gen_type: generate / iterate / proofread).
Streaming is not wired up. Even though Bedrock and the shared client
library (common.bedrock.generate_streaming) support token-by-token
streaming, none of the three endpoints below use it — API Gateway's HTTP
API doesn't support Lambda response streaming, so every call blocks until
Bedrock finishes and returns the full text in one JSON response. If you're
building a UI against these endpoints, don't expect incremental chunks.
Generate
Click "Generate Post" on a triaged idea, and lk-wiz builds a prompt from up to four layers — in increasing priority: a built-in default persona, an optional saved prompt template, an optional one-off system-instruction override, and per-call knobs (audience, tone, language, length) — then sends it to Bedrock and returns the draft text.
POST /api/genai/generate{
"workspace_id": "ws_123",
"idea_id": "idea_456",
"prompt_id": "prompt_789",
"audience": "Engineering leaders",
"tone": "confident",
"length": "medium"
}Up to 5 of the workspace's example posts are pulled in too, ranked by tag overlap with the idea — so if you've tagged your best-performing posts as "examples," GenAI leans on the ones most relevant to what you're writing about.
If you pass a prompt_id that doesn't resolve to a real saved prompt,
generation fails with a 404 rather than silently falling back to a
default. Compare this with Iterate below, which is more
forgiving.
The response is just { "content": "...", "idea_id": "..." } — nothing is
saved. Saving the draft as a real post is a separate step
(POST /api/posts, see Posts § Create).
Iterate
Once you're editing a post in the canvas, the GenAI assistant panel lets you type a natural-language instruction ("make the hook stronger", "add a call to action", "shorten this to 3 paragraphs") and get back a rewritten version.
POST /api/genai/iterate{
"workspace_id": "ws_123",
"post_id": "post_abc",
"instruction": "Make the hook stronger and add a call to action",
"current_content": "Original draft text..."
}This call never touches the post — it returns a suggestion string for
the panel to display. Accepting it is a separate client-side action that
replaces the editor content and records a genai_accept version snapshot
(see Posts § Versions); rejecting it just
discards the response.
Unlike Generate, an unresolved prompt_id here does not error — it
silently falls back to a generic "edit this post" persona. Iteration
always has something reasonable to fall back to; generation from scratch
does not.
Proofread
While you type, lk-wiz automatically re-checks your draft for grammar, tone, LinkedIn-specific issues (character count vs. the 3000-char cap, too many emoji, hashtag count), roughly 3 seconds after you stop typing.
POST /api/genai/proofread{ "workspace_id": "ws_123", "post_id": "post_abc", "content": "..." }The response is a list of annotations, each anchored to a [start, end]
character range in the text, with a type (grammar / tone /
suggestion), a human-readable message, and a proposed suggestion
replacement. Click an annotation in the editor to apply or dismiss it.
Proofreading never fails outright — if the model's response can't be parsed as a JSON array (malformed output, wrapped in prose, etc.), you just get an empty annotation list back, not an error toast.
MCP vs. HTTP API
If you're driving lk-wiz from an AI client (Claude Desktop, Claude Code)
rather than the web UI, the GenAI MCP tools look similar —
generate_post and iterate_post — but behave differently under the
hood:
- They persist.
generate_postimmediately creates a new draft post in the pipeline;iterate_postimmediately overwrites the target post's content. There's no "preview, then accept" step like the web UI's canvas — an MCP call changes real data right away. - Less prompt customization. No
overrides,audience/tone/language/lengthknobs, or tag-ranked examples — just an optionalprompt_idfor generation, and no persona customization at all for iteration. - No proofreading tool. Proofreading is HTTP-API/web-UI only.
See GenAI MCP tools for the full contract.
See also
- GenAI API reference — full request/response shapes and error codes.
- GenAI MCP tools —
generate_post/iterate_postfor AI clients. - Ideas feature guide — where generation starts from.
- Posts feature guide — where generated/iterated content
ends up living, including the
genai_acceptversion trigger.