# Application SDKs
Generated: 2026-11-03T06:48:22.437Z
Source build: local
Canonical docs: https://teammately.ai/docs
---
id: sdks.overview
title: Application SDKs
summary: Choose a server-side SDK and follow a complete Fieldloop submission and receipt example.
kind: reference
product_area: developer_tools
status: stable
updated: 2026-10-31
canonical: /docs/sdks
---
# Application SDKs
## Definition
Use an application SDK inside a backend service, worker or serverless function. Supply its API key through the deployed host's secret mechanism. These libraries do not install the CLI, open browser login, discover credentials or run a local evaluator.
## Choose a language
| Guide | Package identity | Runtime | Resources |
| --- | --- | --- | --- |
| [Python](/docs/sdks/python) | `teammately` | Python 3.10+ | Fieldloop |
| [JavaScript / TypeScript](/docs/sdks/typescript) | `@teammately/sdk` | Node.js 22+, ES modules | Fieldloop |
| [Go](/docs/sdks/go) | `github.com/teammately/teammately-go` | Go 1.25.1+ | Fieldloop and evaluation operations |
Each guide describes installation from a source checkout and a batch call. Resource coverage differs across languages. Use [REST](/docs/public-api) or the [CLI](/docs/cli) for evaluation workflows outside your language client's resource surface.
## Fields, states, or lifecycle rules
A new Fieldloop Submission key authorizes that capability across its workspace. The application supplies organization, Project and source identifiers; current server permissions apply. Older restricted keys retain their restrictions.
`source_event_id` and batch idempotency keys belong to your application. Project/source IDs and receipts are issued by Teammately. In-memory enqueue, durable admission and completed processing are different acknowledgements.
Read [Delivery and Recovery](/docs/sdks/delivery-and-recovery) before continuous ingestion. It covers immutable batches, retries, shutdown, row outcomes and privacy.
## Related task pages
{% related-card-grid %}
- [Python quickstart](/docs/sdks/python)
- [TypeScript quickstart](/docs/sdks/typescript)
- [Go quickstart](/docs/sdks/go)
- [Capture and Inspect Logs](/docs/fieldloop/ingest-logs)
{% /related-card-grid %}
---
id: sdks.delivery
title: SDK Delivery and Recovery
summary: Understand batch identity, retries, memory buffering, shutdown and processing outcomes across SDKs.
kind: reference
product_area: developer_tools
status: stable
updated: 2026-10-31
canonical: /docs/sdks/delivery-and-recovery
---
# SDK Delivery and Recovery
## Definition
Your application chooses what to capture, how to redact it, how long to wait and how to retain source records. The SDK preserves captured data and logical batch identity during submission.
## Fields, states, or lifecycle rules
| Acknowledgement | What it establishes |
| --- | --- |
| Ingestor `add` / `Add` returns | A copied record is in memory |
| Submission returns a receipt | Durable server admission is known |
| Receipt becomes `processed` | Processing finished; inspect all row counts |
| Receipt is `failed`, `cancelled` or `deleted` | Terminal outcome to inspect |
Buffers are memory-only, with no disk outbox or crash-delivery guarantee. Keep original records until admission is known.
## Immutable batches and retries
Prepare a batch once and retain its bytes and application-owned key. Transient `429`, `502`, `503`, `504` and uncertain network failures retry identical bytes/key. `Retry-After` is honored independently of backoff. Permanent failures return directly.
Default retry counts and operation durations are uncapped unless the caller supplies limits or cancellation. Choose explicit application policies. A deadline stops the wait, not durable server work.
Python `Batch.restore`, TypeScript `Batch.restore` and Go `RestoreBatch` retain original bytes for caller-owned recovery. Keep these bytes secure. Re-encoding changed content under the same key can conflict.
## Continuous ingestion and shutdown
Capacities default to uncapped; caller-selected capacities include in-flight rows and can apply backpressure. Automatic dispatch has no imposed delay. Explicit flush and close drain serially.
A failed batch remains pending and pauses automatic flushing. Inspect status/pending batch, correct the failure and retry flush or close. Close stops new input and scheduling, consumes an in-flight result and attempts to drain. A failed or timed-out close can be retried.
Receipt callbacks report admission, not processing. Return promptly. Python callbacks can run on background threads; callbacks must not close their own ingestor. Go callbacks run outside locks.
## Privacy and errors
Select and redact captured content before submission; the SDK does not automatically scrub it. Keep keys on the server. HTTPS is required outside loopback; credentials do not follow redirects. SDKs do not emit telemetry or discover stored login credentials.
Inspect structured API errors and processing receipts. A processed batch can have rejected or conflicting rows; an unknown transport outcome is not a confirmed rejection.
## Related task pages
{% related-card-grid %}
- [Python](/docs/sdks/python)
- [TypeScript](/docs/sdks/typescript)
- [Go](/docs/sdks/go)
- [Fieldloop troubleshooting](/docs/troubleshooting/fieldloop)
{% /related-card-grid %}
---
id: sdks.go
title: Go SDK Quickstart
summary: Consume the Go source module and use context-aware Fieldloop batch and receipt operations.
kind: quickstart
product_area: developer_tools
status: stable
updated: 2026-10-31
canonical: /docs/sdks/go
---
# Go SDK Quickstart
## Prerequisites and installation
Use Go 1.25.1+ and a `teammately-go` source checkout. In an application without an existing workspace:
```sh
go work init . /path/to/teammately-go
```
For an existing workspace, use `go work use /path/to/teammately-go`. Keep machine-local workspace configuration out of published module dependencies. The SDK module is `github.com/teammately/teammately-go`.
## Submit and inspect a batch
Inject `TEAMMATELY_API_KEY` through the host secret mechanism and configure the three destination identifiers below. This complete program sends one fictional record:
### Example: Context-aware batch submission
```go
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"os"
teammately "github.com/teammately/teammately-go"
"github.com/teammately/teammately-go/fieldloop"
)
func main() {
if err := capture(context.Background()); err != nil { log.Fatal(err) }
}
func capture(ctx context.Context) error {
client, err := teammately.New(teammately.Config{
APIKey: os.Getenv("TEAMMATELY_API_KEY"),
})
if err != nil { return err }
scope := fieldloop.Scope{
Organization: os.Getenv("TEAMMATELY_ORGANIZATION"),
Project: os.Getenv("TEAMMATELY_PROJECT"),
Source: os.Getenv("TEAMMATELY_FIELDLOOP_SOURCE"),
}
batch, err := fieldloop.PrepareBatch([]fieldloop.Log{{
SourceEventID: "support-ticket-1042:reply",
OccurredAt: "2026-10-31T09:30:00Z",
Input: json.RawMessage(`{"question":"Has my bicycle shipped?"}`),
Output: json.RawMessage(`{"reply":"Your bicycle is being packed."}`),
}}, "support-ticket-1042:batch-1")
if err != nil { return err }
receipt, err := client.Fieldloop.SubmitPrepared(
ctx, scope, batch, teammately.RetryPolicy{})
if err != nil { return err }
processed, err := client.Fieldloop.WaitReceipt(
ctx, scope, receipt.BatchID, fieldloop.PollOptions{})
if err != nil { return err }
fmt.Println(processed.AcceptedCount, processed.DuplicateCount,
processed.ConflictCount, processed.RejectedCount)
return nil
}
```
Pass the application's context and optional deadline in real services. Teammately supplies destination IDs; your application owns event/batch keys. `json.RawMessage` preserves captured JSON numbers.
## Continuous ingestion and evaluations
Use `fieldloop.NewIngestor(ctx, client.Fieldloop, scope, options)` for continuous ingestion. `Add` acknowledges memory; `Close` drains. Retain source records until admission is known. [Delivery and Recovery](/docs/sdks/delivery-and-recovery) explains pending batches and processing receipts.
`client.Evaluations` provides scoped context, criteria, results, comparisons, external submissions and managed API operations through `evaluations.Scope`. It does not package source or run an evaluator. Use the [CLI](/docs/cli) for local-file workflows.
## Related reference pages
{% related-card-grid %}
- [Fieldloop API](/docs/public-api/fieldloop)
- [Delivery and recovery](/docs/sdks/delivery-and-recovery)
- [Fieldloop troubleshooting](/docs/troubleshooting/fieldloop)
{% /related-card-grid %}
---
id: sdks.python
title: Python SDK Quickstart
summary: Install from source, submit a captured Fieldloop batch and inspect its processing receipt.
kind: quickstart
product_area: developer_tools
status: stable
updated: 2026-10-31
canonical: /docs/sdks/python
---
# Python SDK Quickstart
## Prerequisites and installation
Use Python 3.10+ and a source checkout of `teammately-python`. In your application's virtual environment:
```sh
python -m pip install /path/to/teammately-python
```
The distribution and import are both `teammately`. Configure `TEAMMATELY_API_KEY` through your host's secret mechanism, plus the existing organization, Project and source identifiers used below.
## Submit and inspect a batch
### Example: Capture one application record
```python
import os
from teammately import Batch, Client, FieldloopScope
client = Client(api_key=os.environ["TEAMMATELY_API_KEY"])
scope = FieldloopScope(
organization=os.environ["TEAMMATELY_ORGANIZATION"],
project=os.environ["TEAMMATELY_PROJECT"],
source=os.environ["TEAMMATELY_FIELDLOOP_SOURCE"],
)
logs = [{
"source_event_id": "support-ticket-1042:reply",
"occurred_at": "2026-10-31T09:30:00Z",
"input": {"question": "Has my bicycle shipped?"},
"output": {"reply": "Your bicycle is being packed."},
}]
batch = Batch.prepare(logs, idempotency_key="support-ticket-1042:batch-1")
receipt = client.fieldloop.submit_batch(scope, batch)
processed = client.fieldloop.wait_receipt(scope, receipt.batch_id)
print(processed.accepted_count, processed.duplicate_count,
processed.conflict_count, processed.rejected_count)
```
Replace this fictional record with selected, redacted application content. Your application owns event and batch keys; keep the key stable for the same logical batch. Teammately supplies destination and receipt IDs.
## Continuous ingestion
Create `client.fieldloop.ingestor(scope)`, call `add(log)`, then `close()` at shutdown. A context manager also closes it. `add` acknowledges memory. Optional capacities and deadlines are chosen by the caller; defaults do not impose a capacity or operation deadline.
Callbacks can run on a background thread: keep them thread-safe, return promptly and do not close the ingestor from them. This is a synchronous client. Async applications can use `asyncio.to_thread` for blocking calls. See [Delivery and Recovery](/docs/sdks/delivery-and-recovery).
## Success and recovery
Inspect row counts even when the batch is `processed`. A `ReceiptError` exposes its terminal processing receipt as `error.receipt`. Retain source records until admission is known; retry uncertain submission with the original bytes and key.
## Related reference pages
{% related-card-grid %}
- [SDK delivery and recovery](/docs/sdks/delivery-and-recovery)
- [Fieldloop API](/docs/public-api/fieldloop)
- [Fieldloop troubleshooting](/docs/troubleshooting/fieldloop)
{% /related-card-grid %}
---
id: sdks.typescript
title: JavaScript and TypeScript SDK Quickstart
summary: Use the server-side ES module SDK to submit a Fieldloop batch and inspect row processing.
kind: quickstart
product_area: developer_tools
status: stable
updated: 2026-10-31
canonical: /docs/sdks/typescript
---
# JavaScript and TypeScript SDK Quickstart
## Prerequisites and installation
Use Node.js 22+, ES modules and a source checkout of `teammately-js`. Build the checkout with its npm workflow:
```sh
# In the SDK checkout:
npm ci
npm run build
# In an npm application:
npm install /path/to/teammately-js
```
For an application using another package manager, use that manager's local-package installation workflow. The package is `@teammately/sdk` and includes TypeScript declarations. Inject the API key through your server host's secret mechanism and configure the three destination variables below.
## Submit and inspect a batch
### Example: Submit an immutable captured batch
```typescript
import { Batch, Client, ReceiptError } from "@teammately/sdk";
const client = new Client({ apiKey: process.env.TEAMMATELY_API_KEY! });
const scope = {
organization: process.env.TEAMMATELY_ORGANIZATION!,
project: process.env.TEAMMATELY_PROJECT!,
source: process.env.TEAMMATELY_FIELDLOOP_SOURCE!,
};
const batch = Batch.prepare([{
source_event_id: "support-ticket-1042:reply",
occurred_at: "2026-10-31T09:30:00Z",
input: { question: "Has my bicycle shipped?" },
output: { reply: "Your bicycle is being packed." },
}], "support-ticket-1042:batch-1");
const receipt = await client.fieldloop.submitBatch(scope, batch);
try {
const processed = await client.fieldloop.waitReceipt(scope, receipt.batch_id);
console.log(processed.accepted_count, processed.duplicate_count,
processed.conflict_count, processed.rejected_count);
} catch (error) {
if (error instanceof ReceiptError) {
console.error("Batch processing ended:", error.receipt.status);
}
throw error;
}
```
Replace this fictional application record and its application-owned keys with selected, redacted records. Teammately issues destination and receipt IDs. Keep credential-bearing SDK code on the server.
## Cancellation and continuous ingestion
Operations accept `signal` and `timeoutMs`. Create an ingestor with `client.fieldloop.ingestor(scope)`, use `await ingestor.add(log)`, and drain with `await ingestor.close()` in a `finally` block.
`add` acknowledges memory. Failed batches remain in `status` and `pendingBatch`; recover with their original bytes/key. Defaults impose no capacity or operation deadline. Receipt callbacks must return promptly. See [Delivery and Recovery](/docs/sdks/delivery-and-recovery).
## Success and recovery
Inspect row counts after processing. Preserve `ReceiptError.receipt` for terminal processing outcomes. `Batch.prepare` rejects unsafe numeric integers; use `Batch.restore(originalBytes, originalKey)` when exact JSON bytes, including large integer literals, must be retained.
## Related reference pages
{% related-card-grid %}
- [Delivery and recovery](/docs/sdks/delivery-and-recovery)
- [Fieldloop API](/docs/public-api/fieldloop)
- [Fieldloop troubleshooting](/docs/troubleshooting/fieldloop)
{% /related-card-grid %}
---
id: fieldloop.ingest
title: Capture and Inspect Logs
summary: Configure a source destination, submit captured application records, and distinguish durable admission from processing completion.
kind: task
product_area: fieldloop
status: stable
updated: 2026-10-30
canonical: /docs/fieldloop/ingest-logs
---
# Capture and Inspect Logs
Capture the application facts that explain a behavior question. Keep the original records until their admission is known.
## Prerequisites
- The intended workspace, Project and Fieldloop source.
- Authorization to submit to that destination.
- Actual captured content and stable application event identities.
- Explicit source processing consent where screening is enabled.
## Submit captured records
Use the source's supported submission path with the configured destination. Application-library calls can submit batches and inspect receipts without installing a CLI or signing in through a browser.
Follow the [Python](/docs/sdks/python), [TypeScript](/docs/sdks/typescript) or [Go](/docs/sdks/go) quickstart for a complete batch example, or use the [Fieldloop REST guide](/docs/public-api/fieldloop).
Provide a Fieldloop submission credential through your application's approved secret mechanism. A newly created Fieldloop key grants that capability across its workspace; the sender still identifies the Project and source. Existing more restricted keys keep their restrictions.
Preserve the exact batch content and idempotency key when recovering an uncertain request. A successful admission does not mean every row has completed processing.
## Inspect Logs
Open Logs, choose the intended time range and source, then inspect the original record, relationships and processing state. Captured messages, context, trajectories and feedback remain distinct fields rather than a synthesized replacement for what happened.
Read receipt counts for accepted, duplicate, conflicting and rejected rows. A processed batch can still contain row-level outcomes that need attention.
## Object and state changes
Submission records durable intake and admits processing work. Processing publishes the captured log and its attributable snapshot. Further analysis can create or update Threads separately.
SDK buffering can acknowledge memory before server admission. It is not a disk outbox or a guarantee of crash delivery. Caller-owned cancellation and recovery should preserve the exact source records and batch identity.
## Success criteria
- Records reached the intended Project and source.
- Original content and event identities are preserved.
- Admission and processing outcomes are understood separately.
- Credentials do not appear in logs, reports or copied tasks.
## Common failure modes
- Using a key for another workspace.
- Re-encoding changed content under the same retry identity.
- Treating receipt polling as a new submission.
- Assuming a captured record was analyzed without source consent.
- Treating temporary client buffering as durable admission.
## Related reference pages
{% related-card-grid title="Related reference pages" %}
- [Fieldloop](/docs/fieldloop)
- [Read Fieldloop Threads](/docs/fieldloop/threads)
- [API Keys and Delegated Access](/docs/admin-console/api-keys)
{% /related-card-grid %}
## Related troubleshooting pages
{% related-card-grid title="Related troubleshooting pages" %}
- [Fieldloop Intake and Processing](/docs/troubleshooting/fieldloop)
- [Permissions troubleshooting](/docs/troubleshooting/permissions)
{% /related-card-grid %}
---
id: admin-console.api-keys
title: API Keys and Delegated Access
summary: Choose the intended credential capability and keep workspace keys, delegated users, and browser access distinct.
kind: reference
product_area: admin_console
status: stable
updated: 2026-10-30
canonical: /docs/admin-console/api-keys
---
# API Keys and Delegated Access
## Definition
Use **Admin → API Keys** to manage workspace-owned credentials. A credential's base capability, optional restrictions and the destination's current permissions determine what a request can do.
## Fields, states, or lifecycle rules
- The UI offers Full Access, Read Only and Fieldloop Submission.
- The full key value is shown at creation; later lists use a masked value.
- Renaming a key does not broaden its access.
- Changing access requires issuing the intended credential.
- Deleting a key removes its future credential path.
- Expiry and project/action restrictions, when supplied, narrow the base capability.
## Fieldloop Submission
A new Fieldloop key has the workspace-wide Fieldloop submission capability. Its application sender still specifies the intended Project and source. Current workspace, destination and source authority are rechecked by the backend.
Future sources in the same workspace do not require copying the key into every source policy. Existing keys issued with narrower Project or source restrictions keep those restrictions.
Supply the key through the application's approved secret mechanism. This ingestion path does not require CLI login, browser authentication or expanded login grants.
## Delegated developer access
External Agents benchmark operations can also use delegated native login with explicit read/write scopes and current project read/manage permission. That user principal is different from an API-key principal.
Browser cookie authentication remains the interactive app path. Do not substitute a browser cookie for a server credential or assume a delegated token is accepted on every API route.
## Scope and safe handling
Use an explicit organization, Project, Benchmark and Version for the operation. Keep the key out of copied agent tasks, source files, Case materials and logs. A stable resource ID is not an authorization grant.
The supported external contract defines endpoint schemas and required capability. An internal route or a visible key-management screen does not establish an unrestricted customer API.
## Related task pages
{% related-card-grid title="Related task pages" %}
- [Capture and Inspect Logs](/docs/fieldloop/ingest-logs)
- [Work with External Agents](/docs/improve/external-agents)
- [Permissions](/docs/reference/permissions)
- [Admin Console](/docs/admin-console)
{% /related-card-grid %}