Jangada AIJangada AI

Differences from Python

The npm package jangada-ai follows the behavior of the Python lib: same providers, same retry and fallback policy, same usage contract, same price table. Behavior that differs from Python is treated as a bug, except for the differences listed here, which exist because of the runtime or JavaScript conventions.

Language and API

TopicPythonJavaScript / TypeScript
Sync and asynccomplete and acomplete, stream and astreamasync only: complete returns a Promise, stream returns an AsyncIterable
Namessnake_case (max_tokens, tool_calls, with_fallback)camelCase (maxTokens, toolCalls, withFallback)
Optionskwargs (complete(p, images=[...]))object as the last argument (complete(p, { images: [...] }))
Template variablescomplete(prompt, name="Ana")complete(prompt, { variables: { name: "Ana" } })
Template with an objectstr(value)objects and arrays become JSON
Structured outputPydantic classZod, Standard Schema (Valibot, ArkType) or jsonSchema()
Toolsa function becomes a tool through its signaturetool({ name, parameters, execute })
BytesbytesUint8Array
Cancellationnonesignal?: AbortSignal on every network call
Timeseconds (backoff_base, ttl, poll_interval)milliseconds (backoffBaseMs, ttlMs, pollIntervalMs, timeoutMs)
Usageinput_tokens, cache_read_tokensinputTokens, cacheReadTokens (the observability payload converts them)
Graphgraph.then(a, b)graph.connect(a, b) (a then method would break await graph)
Flow/Graph contextrun(**ctx), with reserved namesrun(ctx), a separate object, no reserved names
Parallel branches with a failurecancels the asyncio taskscancels the branches through AbortSignal
Closing clientsclose()/aclose() and with LLM(...)await llm.close() or await using llm = new LLM(...)

Package and runtime

The core runs on Node 22+, Bun, Deno and edge (Cloudflare Workers, Vercel Edge), so it does not touch the disk. What depends on Node lives in subpaths.

ImportContents
jangada-aiLLM, errors, prices, cache, guardrails, vision, documents, Flow, Graph, Agent, Squad, observability, prompts
jangada-ai/node.env, readImage, readAudio, readDocument, runInSession, serveMcp, serveA2a
jangada-ai/mcpMCP client and server, Code Mode
jangada-ai/ragRAG, chunking, rerank, stores
jangada-ai/evalDataset, Evaluator, evaluate
jangada-ai/prebuiltready-made tools
jangada-ai/a2aweb-standard A2A server
TopicPythonJavaScript / TypeScript
.envloaded on import jangada_ailoaded on import "jangada-ai/node" or with loadEnv(); turn off with JANGADA_NO_DOTENV=1
Image from diskimages=["photo.jpg"], Image.from_pathreadImage("photo.jpg"); in the core, ImagePart, data URI or URL
Audio from disktranscribe("audio.mp3")transcribe(await readAudio("audio.mp3"))
Document from diskfiles=["a.pdf"], Document("a.pdf")readDocument("a.pdf") or new Document(bytes, { name })
Document dependenciespypdf, python-docx, openpyxl ([files] extra)unpdf, mammoth, exceljs; @napi-rs/canvas for PDF through vision
Dataset.from_jsonlfile pathDataset.fromJsonl(text)
Mistral OCRaccepts a pathbytes, URL or data URI only (a path throws UnsupportedError)
Price catalog cachedisk (~/.cache/jangada), 1-day TTLmemory, 1-day TTL per process
SDKspip extrasoptional peerDependencies, loaded with import() only when the provider is used

Observability and prompts

TopicPythonJavaScript / TypeScript
Sessionwith observability_session(...) as trace_idobservabilitySession() passed in { trace }, or runInSession(opts, fn) from jangada-ai/node
Flush at exitatexitbeforeExit with jangada-ai/node; in serverless, await flushObservability()
Prompt used in the tracewith p.use():{ trace: p.trace() }
MCP request contextContextVar2nd argument of execute (ctx) and AsyncLocalStorage when available

Errors, cache and guardrails

TopicPythonJavaScript / TypeScript
classifyHTTP status and class namealso Node network cause.code (ECONNRESET, UND_ERR_CONNECT_TIMEOUT...)
Custom guardrailcheck_input and acheck_input, GuardResult(ok, reason)async checkInput only, returns { ok, reason }
Judge reentrancyContextVara marker on the judge's own call (works in any runtime)
detectObjectsaccepts a path; JSON outside the schema may become OutputValidationErrorImagePart only; reading is always lenient (invalid boxes are dropped)

Providers

TopicPythonJavaScript / TypeScript
Groqgroq SDKopenai SDK with the Groq URL
Ollamaollama SDKdirect fetch to the native API (runs on edge)
Gemini, structured outputresponse_schema (Pydantic)responseJsonSchema (JSON Schema)
Gemini, profiles and extrasthinking_budget, top_pthinkingBudget, topP (@google/genai vocabulary)
Profile warningsdebug log (logging, jangada_ai logger)a profile: ... line in the debug: true trace
Gemini, embeddingsembed(..., output_dimensionality=768)embed(texts, { outputDimensionality: 768 })
Gemini with MCPSDK AFC; usage from the last response onlyjangada's loop; usage summed across rounds
Gemini Interactionspoll_interval/timeout in seconds, sync and asyncpollIntervalMs/timeoutMs, async only, signal cancels polling
Mistral parsechat.parse with Pydanticstrict json_schema responseFormat
Mistral stream with native toolsUnsupportedErrorregular Conversations API call, text in one piece
Mistral toolChoice by name (Conversations API)acceptedUnsupportedError (the JS SDK only accepts auto, none, any, required)
Cohere and Voyage rerankSDKsdirect HTTP API
RAG BM25rank_bm25own implementation, same formula
pgvectorone psycopg connectionpg Pool (injectable), same advisory lock as Python

MCP and A2A

TopicPythonJavaScript / TypeScript
Code ModePython in the Monty sandboxJavaScript in QuickJS (quickjs-emscripten); only return yields a value
MCP server HTTP appStarlette ASGIweb-standard Request => Response handler (Node, Bun, Deno, Workers, Hono, Next)
serve_mcpblocksserveMcp() returns { url, port, close() }
authToken and OPTIONS401 on the preflight tooOPTIONS passes without a token (browser clients)
keepAlive and HTTP 4044xx does not reconnect404 reconnects (expired session, per the spec)
SSRF in the ready-made toolsresolves DNS and checks each IPchecks the literal host; setResolveHost turns on DNS checking
A2Abuild_a2a_app (Starlette)web-standard buildA2aHandler or serveA2a from jangada-ai/node; TTLs in ms

Related: Getting started, Providers, Python lib docs.

On this page