langchain-magic-hour
v0.1.0
Published
Magic Hour tools for LangChain.js — AI video (Sora 2, Veo 3.1, Kling 3.0, Seedance, WAN 2.2) and image generation as LangChain tools.
Downloads
46
Maintainers
Readme
langchain-magic-hour
Magic Hour tools for LangChain.js and LangGraph.js. One API key gives your agents AI video generation (Sora 2, Veo 3.1, Kling 3.0, Seedance, MiniMax H3, WAN 2.2, LTX 2.3) and image generation (GPT-image, Nano Banana Pro, Seedream, Flux, Z-Image).
Install
npm install langchain-magic-hour @langchain/coreGet a free API key at magichour.ai/developer (400 credits on signup + 100/day, no card) and export it:
export MAGIC_HOUR_API_KEY=mh_...Quickstart (LangChain agent)
import { createAgent } from "langchain";
import { ChatOpenAI } from "@langchain/openai";
import { createMagicHourTools } from "langchain-magic-hour";
const agent = createAgent({
model: new ChatOpenAI({ model: "gpt-4o-mini" }),
tools: [...createMagicHourTools()], // reads MAGIC_HOUR_API_KEY
});
const res = await agent.invoke({
messages: [{ role: "user", content: "Make a 5s 480p video of a corgi surfing with a free model and give me the URL." }],
});
console.log(res.messages.at(-1)?.content);Using LangChain 0.3 / @langchain/langgraph/prebuilt? Swap createAgent for createReactAgent({ llm, tools }) — the tools are standard StructuredTools and work with both.
Tools
| Tool | Input | Output (JSON string) |
|---|---|---|
| magic_hour_text_to_video | prompt, model="wan-2.2", duration_seconds=5, resolution="480p", aspect_ratio="16:9", audio?, name? | {project_id, status, video_url, credits_charged, width, height, fps} |
| magic_hour_image_to_video | image (https URL, local path or data URL), prompt, model, duration_seconds, resolution, name? | same as above |
| magic_hour_generate_image | prompt, model="default", image_count=1, aspect_ratio="1:1", name? | {project_id, status, image_urls, credits_charged} |
Each factory accepts an optional config:
import { magicHourTextToVideo, magicHourImageToVideo, magicHourGenerateImage } from "langchain-magic-hour";
const t2v = magicHourTextToVideo({
apiKey: process.env.MAGIC_HOUR_API_KEY, // default
baseURL: "https://api.magichour.ai/v1", // default
fetch: globalThis.fetch, // default; inject for tests/proxies
pollIntervalMs: 5_000, // default; how often to poll the project
timeoutMs: 10 * 60_000, // default; give up after 10 min
waitForCompletion: true, // false => return {project_id, status:"queued"} immediately
});
// Call without an LLM:
const out = JSON.parse(await t2v.invoke({ prompt: "a corgi surfing", model: "wan-2.2", duration_seconds: 5 }));
console.log(out.video_url);Tools submit the job, then poll GET /v1/video-projects/{id} (or /image-projects/{id}) every 5 seconds until the status is complete, error or canceled. Failed jobs are refunded automatically by Magic Hour.
LangGraph
import { StateGraph, MessagesAnnotation, END } from "@langchain/langgraph";
import { ToolNode } from "@langchain/langgraph/prebuilt";
import { ChatOpenAI } from "@langchain/openai";
import { createMagicHourTools } from "langchain-magic-hour";
const tools = [...createMagicHourTools()];
const model = new ChatOpenAI({ model: "gpt-4o-mini" }).bindTools(tools);
const graph = new StateGraph(MessagesAnnotation)
.addNode("agent", async (state) => ({ messages: [await model.invoke(state.messages)] }))
.addNode("tools", new ToolNode(tools))
.addEdge("__start__", "agent")
.addConditionalEdges("agent", (s) => {
const last = s.messages.at(-1) as { tool_calls?: unknown[] };
return last.tool_calls?.length ? "tools" : END;
})
.addEdge("tools", "agent")
.compile();
await graph.invoke({ messages: [{ role: "user", content: "Generate an image of a lighthouse at dusk." }] });Models
Video (credits per second of output)
| Model | Credits/s | Durations (s) | Notes |
|---|---|---|---|
| wan-2.2 | 24 | 3-10, 15 | Free tier. Default. |
| ltx-2.3 | 24 | 1-10, 15, 20, 25, 30 | Free tier. Long clips. |
| minimax-h3 | 24 | 1-10, 15, 20, 25, 30 | Free tier. Max 1080p. |
| seedance-1.5 | 30 | 4-12 | |
| kling-2.6 | 36 | 5, 10 | |
| kling-3.0 | 48 | 3-15 | High-quality motion. |
| veo3.1-lite | 48 | 4, 6, 8, 16, 24, 32, 40, 48, 56 | |
| veo3.1 / veo3.1-audio | 96 | 4, 6, 8, 16, ..., 56 | -audio has native sound. |
| sora-2 | 120 | 4, 8, 12, 24, 36, 48, 60 | Max 720p. |
| seedance-2.0-mini / seedance-2.0 / seedance-2.5 | 96 / 144 / 288 | 4-15 / 4-15 / 4-30 | Max 720p. |
A 5-second wan-2.2 clip at 480p costs 120 credits, well inside the free daily allowance. Resolutions: 480p, 720p, 1080p.
Image
default (cheapest, free tier), gpt-image-2, nano-banana-pro, seedream-5-pro, flux-2-klein, z-image-turbo, qwen-edit.
Model ids are plain strings, so new models work without a package update. See docs.magichour.ai for the live catalogue.
Examples
examples/agent.ts (agent) and examples/direct.ts (no LLM) run live against the API:
MAGIC_HOUR_API_KEY=... npx tsx examples/direct.tsDevelopment
npm install
npm run lint # tsc --noEmit
npm test # vitest, offline (fetch is mocked)
npm run build # tsup -> dist (cjs + esm + d.ts)Other Magic Hour integrations
- Vercel AI SDK provider:
magic-hour-ai-provider - ComfyUI node: comfyui-magic-hour
- MCP server: github.com/magichourhq
- Official SDKs:
magic-hour(Node),magic_hour(Python)
License
MIT
