Connectors, adapters, research
Three packages for building integrations rather than consuming the API directly. If you are writing an application, you want the SDK — these exist for people building a TNL integration into another platform.
@theneuralledger/connectors
Host-neutral actions, signed triggers, and lifecycle contracts. It is what the n8n and Zapier integrations are built on, so a new platform integration behaves identically to the existing ones.
npm install @theneuralledger/connectorsimport { ConnectorClient } from '@theneuralledger/connectors';
const client = new ConnectorClient({ apiKey: process.env.TNL_API_KEY! });
// Fail fast when the user pastes a bad key
await client.validateConnection();
const result = await client.execute('search_intelligence', { query: 'tariff' });run starts a long-running operation and getResult collects it later — the split matters on platforms that time out a synchronous step:
const handle = await client.run('run_research', { question: 'KRW exposure' });
// ... later, in a separate invocation
const research = await client.getResult(handle.id);Polling state
Platforms without webhooks poll. advancePollingState gives you the same cursor semantics the built-in integrations use, so you neither miss nor repeat items:
import { advancePollingState } from '@theneuralledger/connectors';
let state = loadState();
const { items, nextState } = await advancePollingState(client, state);
for (const item of items) await handle(item);
saveState(nextState);Persist nextState after processing, not before. If the process dies mid-batch you will reprocess a few items, which is recoverable; advancing first loses them permanently.
Deduplication
import { MemoryConnectorDedupeStore } from '@theneuralledger/connectors';Fine for a single process. Behind several workers, implement the same interface over shared storage.
@theneuralledger/adapters
Contracts and presentation helpers for AI clients — capability negotiation, task shaping, error normalisation, and rendering.
import {
negotiateCapabilities,
buildResearchTask,
renderResearchMarkdown,
normalizeAdapterError,
} from '@theneuralledger/adapters';
const profile = negotiateCapabilities(hostCapabilities);
const task = buildResearchTask({ question, profile });
const markdown = renderResearchMarkdown(result);negotiateCapabilities is the useful part: hosts differ in what they support — streaming, tool calls, attachments — and it resolves a profile rather than making you branch per host.
normalizeAdapterError maps host-specific failures onto one error shape, so your integration reports the same thing everywhere.
@theneuralledger/research
Evidence-first research orchestration: budgets, caching, evidence collection, and result storage.
import { HttpEvidenceAdapter, InMemoryResearchResultStore } from '@theneuralledger/research';Research runs cost real quota, so the package makes budgets explicit and throws ResearchBudgetExceededError rather than silently spending more:
import { ResearchBudgetExceededError } from '@theneuralledger/research';
try {
await runResearch(task);
} catch (error) {
if (error instanceof ResearchBudgetExceededError) {
// narrow the question or raise the budget deliberately
}
}The Deterministic* adapters return fixed results for tests, and the Disabled* adapters refuse to run — useful for a build that must not reach the network.
InMemoryResearchResultStore loses everything on restart. It is for tests; production needs a durable store behind the same interface.
Which one?
| You are | Use |
|---|---|
| Writing an app that reads intelligence | SDK / Python |
| Adding TNL to an automation platform | connectors |
| Adding TNL to an AI client or IDE | adapters, or the MCP server |
| Running research pipelines | research |