Skip to content

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.

bash
npm install @theneuralledger/connectors
ts
import { 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:

ts
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:

ts
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

ts
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.

ts
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.

ts
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:

ts
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 areUse
Writing an app that reads intelligenceSDK / Python
Adding TNL to an automation platformconnectors
Adding TNL to an AI client or IDEadapters, or the MCP server
Running research pipelinesresearch

The Neural Ledger API