Amazon Bedrock AgentCore can now send content straight to long-term-memory extraction, but HTTP 202 proves only that the request was accepted. Keep the source outside AgentCore, bind one stable client token to its exact version, and do not trust the write until every expected strategy produces an attributable record.
AWS released IngestData on September 8, 2026 for every region where AgentCore Memory is supported. The API removes a real piece of plumbing: content can feed long-term-memory extraction without first becoming a retrievable short-term event. That is useful for backfills, system events and source data your application already retains.
It also creates a sharp evidence boundary. The intake response is not the memory outcome.
HTTP 202 is the start of the write
IngestData returns HTTP 202 and a sessionId. It does not return a memory-record ID, a strategy result or a completed extraction job. AWS describes the operation as asynchronous: records normally appear later, with latency depending on content and strategy configuration.
That leaves four facts to keep separate:
- Intent: the application decided which exact source version may become memory.
- Acceptance: AgentCore accepted that payload under one session.
- Application: configured strategies created, updated or consolidated memory records.
- Observation: your system read back attributable records or authoritative failure evidence.
The request may fan out to several built-in strategies. A single 202 can therefore precede several records, no records yet, or a failed extraction job. Marking the work complete on the API response collapses all of those states into a false success.
This is why direct ingestion is not a replacement for the general memory policy and retrieval contract. It is a narrower intake route for source material whose authoritative copy already exists elsewhere, or whose verbatim form is intentionally disposable.
Retain one external ingestion ledger
The application needs an immutable record before it calls AgentCore. At minimum, retain:
source_ref: the stable business identifier of the raw recordsource_version: the exact source revision or event sequencesource_sha256: a digest of the canonical payload bytesactor_id,session_idand the resolved namespace- the expected strategy IDs
- the
contentTimestamp - the deterministic
clientToken - request time, HTTP status and returned session
- observed memory-record IDs by strategy
- one terminal state and its reason
Derive clientToken from the source reference, version and hash. AgentCore uses a repeated case-sensitive token to suppress the same intake operation. That protects request replay, but it cannot prove that asynchronous extraction completed. Idempotent intake and observed application are different controls.
from hashlib import sha256
def client_token(source_ref: str, source_version: str, source_sha256: str) -> str:
material = f"{source_ref}:{source_version}:{source_sha256}".encode()
return sha256(material).hexdigest()Put the same provenance values in the submitted JSON and in request metadata. Then configure the strategy's metadataSchema to populate those keys on extracted records. This is deliberate duplication: the external ledger proves what was sent, while record metadata creates an attribution path during read-back.
Do not assume arbitrary request metadata automatically survives extraction. AWS states that only keys present in a strategy's metadata schema are populated on extracted records. Keys outside that schema are ignored. If an exact source hash is missing or changed in the resulting record, the honest result is divergent, not close enough.
The request metadata map accepts at most 15 entries. AgentCore also limits a memory to 10 indexed keys and combines up to 5 filters with AND. Spend that index budget on business isolation and deterministic reconciliation fields, not decorative telemetry.
Reconcile every expected strategy
A useful reconciler has six states: prepared, accepted, observed, failed, unavailable and divergent.

- Prepared: the source envelope and token exist, but AgentCore has not accepted the call.
- Accepted: the service returned 202 and the expected session, but record evidence is incomplete.
- Observed: every expected strategy produced an attributable record in the intended namespace.
- Failed: the request failed, or AgentCore exposed an extraction job with a failure reason.
- Unavailable: the observation deadline elapsed without enough authoritative evidence.
- Divergent: a record appeared under the wrong namespace, source version, digest or session relationship.
Use either of AWS's two observation paths. ListMemoryRecords and RetrieveMemoryRecords can read records with their IDs, strategy IDs, namespaces and metadata. Kinesis memory-record streaming can deliver MemoryRecordCreated, MemoryRecordUpdated and MemoryRecordDeleted events; FULL_CONTENT also carries the record text. Whichever path you choose, the external ledger remains the join key and terminal-state record.
For failures, enumerate ListMemoryExtractionJobs until nextToken is empty. The API returns 20 results by default and at most 50 per request, so inspecting one page is not a complete failure check. AWS moves persistent failures to a dedicated queue and exposes a reason code. Repair the cause first, call StartMemoryExtractionJob for the exact job, then run record reconciliation again. A successful redrive request is still not an observed record.
Prepare the envelope
Canonicalize the raw source, calculate its digest, resolve tenant-safe actor and namespace values, name the expected strategies and mint one stable client token.
Record acceptance
Persist the request evidence and returned session. A non-202 response is failed; a different session is divergent; a matching 202 is accepted only.
Observe all records
Consume Kinesis lifecycle events or paginate record APIs. Join on the retained provenance fields and require the complete expected strategy set.
Resolve exceptions
Enumerate failed extraction jobs, retain the failure reason, repair the cause and redrive the exact job. Keep deadline expiry as unavailable rather than inventing a zero.
A 12-case reference classifier
The compact classifier below evaluates retained acceptance, record and failure-job evidence. It has no AWS dependency, so the release gate can run in CI with fixtures before any account credentials exist.
from dataclasses import dataclass
from typing import Iterable, Mapping, Sequence
@dataclass(frozen=True)
class Record:
record_id: str
strategy_id: str
namespace: str
metadata: Mapping[str, str]
def classify(envelope, status_code: int, returned_session: str | None,
records: Sequence[Record], failed_jobs: Iterable[dict],
deadline_elapsed: bool) -> tuple[str, str]:
if status_code != 202:
return "failed", f"ingest returned HTTP {status_code}"
if returned_session != envelope.session_id:
return "divergent", "accepted session differs from request"
if any(job["status"] == "FAILED" for job in failed_jobs):
return "failed", "an extraction job failed"
seen_ids, observed = set(), set()
for item in records:
if item.record_id in seen_ids:
return "divergent", "duplicate record id"
seen_ids.add(item.record_id)
if item.namespace != envelope.namespace:
return "divergent", "unexpected namespace"
if any(item.metadata.get(k) != v for k, v in envelope.provenance.items()):
return "divergent", "provenance mismatch"
observed.add(item.strategy_id)
missing = envelope.expected_strategy_ids - observed
if records and not missing:
return "observed", "every expected strategy has evidence"
if deadline_elapsed:
return "unavailable", f"missing strategies: {sorted(missing)}"
return "accepted", "extraction evidence is incomplete"The dependency-free reference implementation passed 12 local unit tests. The cases covered deterministic tokens, version-sensitive tokens, bare 202 acceptance, non-202 failure, session divergence, failed extraction jobs, a complete strategy set, an incomplete set before and after the deadline, provenance mismatch, duplicate record IDs and namespace divergence.
Those are classifier tests, not an AWS performance benchmark. A real acceptance suite still needs representative payloads, the deployed metadata schema, tenant-bound namespaces, live strategy IDs, the observation path and a deliberately induced failed extraction.
Direct ingestion changes cost shape, not evidence duty
Skipping CreateEvent avoids creating a short-term event you did not need. It does not make long-term memory free. At the current published rates, built-in strategies cost $0.75 per 1,000 stored records per month, built-in-with-override or self-managed strategies cost $0.25 per 1,000 stored records per month, and retrieval costs $0.50 per 1,000 calls.
Model the whole path: source preparation, ingestion, extraction, record storage, retrieval, Kinesis and CloudWatch, failed-job review, redrive and deletion. Divide that joined cost by reconciled source envelopes, not accepted API calls. A cheap 202 with no attributable record has produced no usable memory outcome.
The release rule is simple: direct ingestion is ready only when the source owner accepts the raw-record tradeoff, every request has a stable external envelope, every expected strategy is observed, failures can be redriven without losing identity, and divergent records can be quarantined or deleted.
Does HTTP 202 mean AgentCore created long-term-memory records?
No. It means AgentCore accepted the content for asynchronous processing. Completion requires later record or failure evidence.
Does clientToken prove extraction happened exactly once?
No. It protects repeated intake requests with the same token. The strategies can still be processing, fail, or produce records that your application has not reconciled.
Should IngestData replace CreateEvent?
Only when the verbatim event is already authoritative elsewhere or is intentionally unnecessary. Use CreateEvent when you need AgentCore's retrievable short-term chronology or branching.
How should failed direct ingestions be recovered?
Paginate all failed extraction jobs, retain the reason, repair the root cause, redrive the exact job and reconcile the resulting records again.








