メインコンテンツまでスキップ

Knowledge Bases

AI agent 用の searchable context を保存し、metadata schema、automatic extraction、query-time filtering を使用して管理します。​

Knowledge Base を使用する理由​

knowledge base は、AI agent が質問への回答時に参照する context を保存するものであり、Agent Studio の Knowledge Base ability と同じものです。context を追加すると、agent は基盤となる AI model の一部ではない可能性がある特定 topic に関して relevant な回答を提供できます。

以下は簡単な code example ですが、追加する context はさらに複雑にできます。context の例としては、code documentation、product manual、business operation(例: store hour)、user-specific data などがあります。context type を組み合わせて AI agent 用の堅牢な knowledge base を作成することで、user が必要とするあらゆる情報を agent が提供できるようにします。

Knowledge Base の作成​

agent context を追加または update するには、最初に knowledge base を作成・接続する必要があります。

まず、out of the box で提供される embedding model を使用して新しい knowledge base を作成します。

Client code
await squid.ai().knowledgeBase('banking-knowledgebase').upsertKnowledgeBase({
description: 'This Knowledge Base contains information on card data',
embeddingModel: 'text-embedding-3-small',
chatModel: 'gpt-5.5',
metadataFields: [],
});

または、connector ID、model name、dimension を含む object を渡して、integration-based embedding model を使用できます。setup instruction については、OpenAI Compatible Embedding connectorを参照してください。

Client code
await squid
.ai()
.knowledgeBase('banking-knowledgebase')
.upsertKnowledgeBase({
description: 'This Knowledge Base contains information on card data',
embeddingModel: {
integrationId: 'my-embeddings',
model: 'text-embedding-3-small',
dimensions: 1536,
},
chatModel: 'gpt-5.5',
metadataFields: [],
});

knowledge base は vector を 2 つの backend のいずれかに保存します。'mongoAtlas' は native hybrid fusion、ranked keyword search(Keyword searchを参照)、knowledge graph searchをサポートします。'postgres' はこれらをサポートしません。vectorDbType を省略すると、application が実行される deployment に応じた server default が使用されます。application が特定 backend に依存する場合は明示的に渡してください。backend は作成後に変更できず、getKnowledgeBase() で読み取れます。

Client code
await squid.ai().knowledgeBase('banking-knowledgebase-atlas').upsertKnowledgeBase({
description: 'This Knowledge Base contains information on card data',
embeddingModel: 'text-embedding-3-small',
chatModel: 'gpt-5.5',
metadataFields: [],
vectorDbType: 'mongoAtlas',
});

const kb = await squid.ai().knowledgeBase('banking-knowledgebase-atlas').getKnowledgeBase();
console.log(kb?.vectorDbType); // 'mongoAtlas'

getKnowledgeBase() は保存済み knowledge base record(vectorDbType を含む)で resolve します。該当 ID の knowledge base が存在しない場合は undefined で resolve します。既存の knowledge base に異なる vectorDbType を upsert すると、backend を変更するのではなく error を throw します。

backend は作成時に固定されるため、knowledge graph searchを有効にできるかどうかも決まります。'postgres' 上に作成された knowledge base には graph を追加できません。後で graph が必要になる可能性がある場合は、server default に依存せず vectorDbType: 'mongoAtlas' を渡してください。

Context の Upsert​

knowledge base に context を追加するには、context とその type を渡して upsertContext() method を使用します。

upsertContext() method は context ID を受け取ります。context ID を指定すると、後で変更する際に context により容易に access できます。

Client code
const data = `Platinum Mastercard® Fair Credit, No annual fee. Flexible due dates...`;

await squid.ai().knowledgeBase('banking-knowledgebase').upsertContext({
type: 'text',
title: 'Credit Card Info',
text: data,
contextId: 'credit-cards',
});

または、upsertContexts() を使用して context の array を upsert します。

Client code
const creditCard1 = `Platinum Mastercard® Fair Credit, No annual fee. Flexible due dates...`;
const creditCard2 = `Gold Mastercard®, $50 annual fee. Due dates once a month...`;

await squid
.ai()
.knowledgeBase('banking-knowledgebase')
.upsertContexts([
{
type: 'text',
title: 'Credit Card 1 Info',
text: creditCard1,
contextId: 'credit-cards1',
},
{
type: 'text',
title: 'Credit Card 2 Info',
text: creditCard2,
contextId: 'credit-cards2',
},
]);

個々の context が拒否された場合でも upsertContexts() は resolve し、各 rejection を failures に列挙します。rejection には errorMessage が含まれ、machine-readable class が適用される場合には errorCode も含まれます。

errorCode意味対応
DUPLICATE_CONTENTrequest に contextId がなく、content が knowledge base 内の既存 context と byte-identical です。failure ではありません。duplicateOf が既存 context を指すため、元の保存場所を user に表示できます。
EMBEDDING_FAILEDextraction は成功したものの、context chunk の embedding が失敗しました。何も書き込まれず、overwrite target は以前の content を維持します。そのまま request を retry します。変更せずに replay しても安全です。

Agent への接続​

knowledge base が agent の回答に影響するのは、その agent に接続された後だけです。knowledge base を接続し、agent による使用方法を構成するには、Connect a Knowledge Base to an Agentを参照してください。

Context Type​

text と file の 2 種類の context がサポートされます。

text context は context を含む string で作成します。

Client code
const data = `Platinum Mastercard® Fair Credit, No annual fee. Flexible due dates...`;

await squid.ai().knowledgeBase('banking-knowledgebase').upsertContext({
type: 'text',
title: 'Credit Card Info',
text: data,
contextId: 'credit-cards',
});

file context は、upsertContext() method の 2 番目の parameter として File object を指定して作成します。file は Squid に upload され、file content から context が作成されます。file context は context object(最初の upsertContext() argument)の preferredExtractionMethod field も受け入れます。これは document の extraction 方法を選択します。たとえば legacy_with_llm(Console では Basic + page understanding と表示)は、text とともに各 page の AI description を追加します。Extraction methodsを参照してください。

Client code
const file = new File([contextBlob], 'CreditCardList.pdf', { type: 'application/pdf' });

await squid.ai().knowledgeBase('banking-knowledgebase').upsertContext(
{
type: 'file',
contextId: 'credit-cards',
preferredExtractionMethod: 'legacy_with_llm',
},
file
);
注記

context は任意の長さにできます。ただし、LLM prompt には character limit があるため、実際に user の inquiry とともに含まれるのは context の一部のみである可能性があります。prompt を構築する際、Squid は提供された context のうち、user の質問に最も relevant な部分を判断します。

Spreadsheet File​

file context として upload された spreadsheet file(.csv、.tsv、.xlsx、.xlsm、.xls、.xlsb)は、専用 ingestion pipeline で処理されます。raw cell text を chunk 化する代わりに、Squid は workbook の structure(sheet 名と size、header row、hidden sheet、file format が提供する場合は chart と pivot table)を抽出し、workbook 全体の生成された summary を embed します。したがって、spreadsheet context の search result は cell data の fragment を返すのではなく、workbook に含まれる内容を説明します。

summary は preview であるため、agent は正確な数値についてそれらに依存しません。接続済み knowledge base に spreadsheet context が含まれる場合、agent は sandbox 内で Python を実行して実際の upload 済み file に対する質問に回答する querySpreadsheetsWithAi tool を自動的に取得します。

  • 正確な value: count、sum、average、特定 row または cell の lookup、filter、sort。
  • 複数 workbook にまたがる質問。たとえば file 間の data join または比較を単一 call で行えます。
  • structure および provenance に関する質問: sheet に実際に何が含まれるか、どの sheet が live calculation を提供するか、どの cell が formula か hardcoded input か。formula と dependency の inspection は .xlsx/.xlsm で最も完全、.xls では部分的、.xlsb(cell value のみ)および CSV/TSV(formula metadata なし)では利用できません。

configuration は不要ですが、専用 pipeline と agent tool は保持された original file に依存します。context を discardOriginalFile: true(upsertContext() の file option。default は false。reprocessing と download のために original を保持する代わりに、text extraction 後に保存済み original を破棄するよう Squid に指示します)で upload すると、spreadsheet は plain extracted text として ingestion され、querySpreadsheetsWithAi は提供されません。

Context の取得​

すべての context の list を取得するには、listContexts() method を使用します。この method は、contextId を含む agent context object の array を返します。

Client code
await squid.ai().knowledgeBase('banking-knowledgebase').listContexts();

特定の context item を取得するには、context ID を渡して getContext() method を使用します。

Client code
await squid.ai().knowledgeBase('banking-knowledgebase').getContext('credit-cards');

Context の Page を List 化する​

listContexts() は knowledge base 内のすべての context を返すため、knowledge base に数千 entry が保持されると扱いにくくなります。代わりに listContextsPage() を使用して page ごとに取得し、ID または title で search します。

Client code
const page = await squid
.ai()
.knowledgeBase('banking-knowledgebase')
.listContextsPage({
offset: 0,
limit: 50,
// Truncates each entry's text so a listing stays small.
truncateTextAfter: 500,
// Case-insensitive substring match on context ID and title only, not on the text.
search: 'credit',
});

すべての option は optional です。response には、request した contexts に加え、offset と limit を無視する totalCount が含まれます。そのため、2 回目の call なしで page count を render できます。

search は context ID と title のみを match するため、content により entry を検索するにはsearchingを使用します。truncateTextAfter は TypeScript client でのみ利用できます。

Context の削除​

context entry を削除するには、deleteContext() method を使用します。

Client code
await squid.ai().knowledgeBase('banking-knowledgebase').deleteContext('credit-cards');

指定された context ID に対する entry がまだ作成されていない場合、この method は error になります。

Context Metadata​

AI knowledge base の context を追加または update する際、optional に context metadata を指定できます。metadata は key の type を string、number、boolean にできる object です。metadata を追加すると context に関する追加情報が提供され、agent との interaction 時に使用できます。次の例では PDF を context として追加し、metadata に 2 つの key/value pair を指定しています。

Client code
const file = new File([contextBlob], 'CreditCardList.pdf', { type: 'application/pdf' });

await squid
.ai()
.knowledgeBase('banking-knowledgebase')
.upsertContext(
{
contextId: 'credit-cards',
type: 'file',
metadata: { company: 'Bank of America', year: 2023 },
},
file
);

その後、metadata を使用した context filtering section に示すように、AI agent との chat で metadata を使用できます。

Metadata Schema の定義​

knowledge base で metadata schema を宣言すると、metadata が structured かつ self-maintaining になります。knowledge base を upsert するとき、metadataFields に field definition を渡します。

Client code
await squid
.ai()
.knowledgeBase('banking-knowledgebase')
.upsertKnowledgeBase({
description: 'This Knowledge Base contains information on card data',
embeddingModel: 'text-embedding-3-small',
chatModel: 'gpt-5.5',
metadataFields: [
{ name: 'author', dataType: 'string', required: true, description: 'The full name of the person who wrote the document.' },
{ name: 'publishedAt', dataType: 'date', required: false, description: 'The date the document was published.' },
{ name: 'category', dataType: 'string', required: false, description: 'The document category, for example report, memo, or guide.' },
],
});

各 field definition は以下を持ちます。

FieldTypeRequired説明
namestringYesletter、number、underscore のみ。text や contextId などの reserved name は拒否されます。
dataType'string' | 'number' | 'boolean' | 'date'Yesvalidation と filtering に使用します。date value は epoch millisecond に normalize されるため、range filter が機能します。
requiredbooleanYesfield とともに agent に提示される hint です。extraction や ingestion には影響しません。required value が見つからない場合でも context は ingestion されます。
descriptionstringNodocument から value を抽出するため、また agent が metadata filter を構築する際の guidance に使用します。

TypeScript type は 'array' data type も宣言しますが、まだサポートされておらず、knowledge base schema の保存時に拒否されます。

schema を宣言すると、3 つのことが有効になります。提供された metadata の validation(type が正しくない value はその context のみを拒否します)、欠落 value の automatic extraction、agent-driven filtering です。

Automatic Metadata Extraction​

declared field に value を指定せずに context を upsert すると、field が required とマークされているかどうかにかかわらず、Squid が自動的に入力します。file upload では、まず document property が使用されます。well-known property にちなんだ name の field(title/docTitle、author/docAuthor、createdAt/docCreatedAt、modifiedAt/docModifiedAt、docType)は、PDF および Office document property、markdown front matter、HTML metadata から入力されます。各 field の description による guidance を受け、document text に対する LLM pass が残りの field を処理します。指定した value は常に優先され、上書きされません。ただし例外として empty string は value なしと見なされ、extraction 対象のままです。抽出された field の name は、保存済み context の autoExtractedMetadataFields に記録されます。extraction は best-effort であり、value が見つからない場合でも upload は失敗せず、field は存在しないままになります。

knowledge base にすでに保存された value を基に Squid に field description を作成させるには、generateMetadataFieldDescriptions() を呼び出します。生成された description は保存せずに返されます。review した後、upsertKnowledgeBase() を使用して knowledge base に保存します。

Client code
const { fields } = await squid.ai().knowledgeBase('banking-knowledgebase').generateMetadataFieldDescriptions({ overwriteExisting: false });

Metadata による Knowledge Base Context の Filtering​

context に metadata を追加すると、contextMetadataFilterForKnowledgeBase chat option を使用して、特定 context のみを参照するよう AI agent に指示できます。filter requirement を満たす context のみが、client prompt への response に使用されます。

次の例では、"company" の metadata value が "Bank of America" と等しい context のみを含めるよう filter しています。

Client code
await squid
.ai()
.agent('banking-copilot')
.ask('Which Bank of America credit card is best for students?', {
contextMetadataFilterForKnowledgeBase: {
['banking-knowledgebase']: { company: { $eq: 'Bank of America' } },
},
});

以下の metadata filter がサポートされます。

Filter説明サポートされる type
$eqmetadata value が指定 value と等しい vector に matchnumber、string、boolean
$nemetadata value が指定 value と等しくない vector に matchnumber、string、boolean
$gtmetadata value が指定 value より大きい vector に matchnumber
$gtemetadata value が指定 value 以上の vector に matchnumber
$ltmetadata value が指定 value より小さい vector に matchnumber
$ltemetadata value が指定 value 以下の vector に matchnumber
$inmetadata value が指定 array に含まれる vector に matchstring、number
$ninmetadata value が指定 array に含まれない vector に matchstring、number
$exists指定 metadata field を持つ vector に matchboolean

$underPath による Folder への Scoping​

$underPath は、document の folderPath などの hierarchical string field を subtree に対して match します。value が operand と完全に等しい場合、または operand の後に / が続く場合に match します。

Client code
await squid
.ai()
.agent('banking-copilot')
.ask('What changed in the 2023 reports?', {
contextMetadataFilterForKnowledgeBase: {
['banking-knowledgebase']: { folderPath: { $underPath: 'reports/2023' } },
},
});

この filter は reports/2023 と reports/2023/q1/deck を許可しますが、sibling である reports/2023 drafts を許可することはありません。/ separator が segment boundary を提供するため、raw prefix match では発生する、prefix だけを共有する folder への subtree scoping の leak を防げます。

知っておくべき detail:

  • operand の leading slash と trailing slash は無視されるため、reports/2023/ と reports/2023 は同じ subtree を指定します。
  • empty operand は field を持つすべての context に match します。
  • match は case-sensitive であるため、Reports と reports は別の folder です。
  • folderPath は reserved key ではなく通常の metadata key です。POSIX / separator を使用し、leading/trailing slash なしで記述してください。upload root にある file には absent value ではなく empty string を使用します。
  • $underPath は knowledge base にのみ適用されます。unknown operator を拒否する metrics tag filter または matchmaking では受け入れられません。

bare scalar value は $eq の shorthand です。つまり、{ company: 'Bank of America' } と { company: { $eq: 'Bank of America' } } は同等です。filter は $and と $or を使用して結合することもできます。

Client code
await squid
.ai()
.agent('banking-copilot')
.ask('Summarize recent card reports', {
contextMetadataFilterForKnowledgeBase: {
['banking-knowledgebase']: {
$and: [{ category: 'report' }, { publishedAt: { $gt: Date.parse('2026-01-01') } }],
},
},
});

dataType: 'date' で宣言した field は epoch millisecond として保存されるため、range filter では numeric value(例: Date.parse('2026-01-01'))を渡します。

Agent-driven Metadata Filtering​

knowledge base が metadata schema を宣言している場合、接続された agent は自身で metadata filter を構築できます。knowledge base search tool は filter parameter を取得し、model は各 field の description と tool description に表示される小さな sample value set に基づき、user の質問に応じてこれを設定します。

contextMetadataFilterForKnowledgeBase で設定した filter は常に適用され、AND を使用して agent の filter と結合されます。agent は許可された scope を絞り込むことはできますが、拡張することはできません。そのため app-level filter は security boundary のままです。

接続済み knowledge base で enableMetadataInspection: true を設定すると、agent は field の保存済み value を on-demand で列挙・検索する inspection tool も取得します。これにより正確な filter を構築できます。value は最も最近 update された document から sample されるため、sample に value がないことは、それが存在しないことの証明にはなりません。

Source Permission の尊重​

connector から index 化された content には通常、独自の access rule があります。SharePoint document、Confluence page、Slack conversation は、organization 内の一部の person には表示され、他の person には表示されません。knowledge base はこれらの rule を尊重できるため、agent は chat している person に閲覧が許可された content のみを根拠に回答します。

同じ agent に同じ質問をする 2 人の person は、それぞれが source system で開くことができる document からのみ作成された回答を受け取ります。user が access できない content は取得されず、model に到達せず、citation に表示されることもありません。

これは、質問者ではなく topic または attribute で result を絞り込む metadata filtering とは別のものです。両方を組み合わせることができ、permission は常に適用されます。

注記

user の authentication は引き続き application の責任です。Squid は application が確立する authenticated user identity の permission を適用します。setup については Authentication を参照してください。

Knowledge Base の検索​

search() method を使用して knowledge base を直接 query し、一致する chunk を取得します。

Client code
const chunks = await squid.ai().knowledgeBase('banking-knowledgebase').search({
prompt: 'Which credit cards have no annual fee?',
});

semantic(vector)search は、identifier、error code、SKU、file name など、precision が最も重要な exact token で最も弱くなります。optional な searchMode option は match の検索方法を選択します。各 mode の動作は knowledge base の search backend に依存します。これは knowledge base の作成時に固定され、getKnowledgeBase() で読み取れる vectorDbType('mongoAtlas' または 'postgres')です。

Mode説明
'hybrid'graph のない knowledge base では default です。'mongoAtlas' では semantic candidate と keyword candidate を native に fuse します。'postgres' では semantic search に fallback します。
'vector'semantic similarity のみ。
'keyword'embedding-free lexical search。'mongoAtlas' では、partial match でも最良の result を返す ranked full-text(BM25)matching。'postgres' では unranked filter であり、whitespace-separated term のすべてが chunk 内に literal かつ case-insensitive substring として出現する必要があります。
'graph'entity graph を使用した multi-hop retrieval で、hybrid search と fuse されます。graph が有効な 'mongoAtlas' knowledge base でのみ利用でき、その場合これが default です。Knowledge Graph Searchを参照してください。
Client code
const chunks = await squid.ai().knowledgeBase('banking-knowledgebase').search({
prompt: 'ERR_0000_4F2A',
searchMode: 'keyword',
});

接続済み agent は自身で search mode を選択します。knowledge base search tool は backend がサポートする mode を提供し、agent は質問が exact token を対象とする場合に keyword search に切り替えます。knowledge graphを持つ knowledge base は追加で 'graph' mode を提供し、searchMode が省略された場合にはこれが default になります。

grep による Literal Scan​

上記の各 search mode は、ingestion が text を分割・処理した後に生成される chunk に対して機能します。grep() は代わりに chunk 化前の raw extracted text を scan し、各 matching line とその file を返します。price list の特定 SKU や spreadsheet row 内の value など、意味ではなく character が必要な場合、また surrounding line が重要な場合に使用してください。

Client code
const result = await squid
.ai()
.knowledgeBase('banking-knowledgebase')
.grep('ERR_0000_4F2A', {
// Scopes the scan to matching contexts before any text is read.
metadataFilter: { category: 'runbooks' },
maxMatches: 100,
});

for (const match of result.matches) {
// e.g. "CreditCardList.pdf, page 4, line 12: ..."
console.log(`${match.fileName}, ${match.part}, line ${match.lineNumber}: ${match.line}`);
}

どちらの option も optional です。

OptionType説明
metadataFilterobject[$and、$or、$underPathを含む metadata filtering と同じ grammar を使用し、metadata が match する context に scan の scope を限定します。text の match 前に適用されます。
maxMatchesnumber返す match の最大数。default は 50、上限は 200。

各 match には、取得元の contextId と fileName、part(extractor が提供する場合は sheet または section title、それ以外は page N)、1-based の lineNumber、一致した line、および一致 line と周囲の少数 line を含む context が含まれます。

留意すべき動作:

  • pattern は常に literal です。 regular expression metacharacter は escape されるため、punctuation と symbol はその文字自体に match します。pattern は line をまたぐことができます。
  • match は ASCII letter に対してのみ case-insensitive です。 acme は ACME を検出しますが、café は CAFÉ を検出しません。text が ASCII ではない場合は exact casing で検索してください。

empty の matches array が string の不在を証明するのは、response に limitation がない場合だけです。request した scope に届かなかった scan は、以下のいずれかに limitation を設定します。empty result から結論を出す前に確認してください。

Limitation意味
timedOutscan が server-side deadline に達しました。large knowledge base では通常発生し、pattern の存在については何も示しません。
noIndexedTextscope 内に保存済み text がありません。literal search の導入前に ingestion された context は、再 ingestion されるまでこの状態です。
filterMatchedNoContextsmetadataFilter が context を許可しなかったため、何も読み取られませんでした。
scopeTruncatedmetadataFilter が 1 回の scan で対象にできる context より多くを許可したため、一部のみ検索されました。filter を絞り込んでください。
partsCapReachedscan が 1 call あたりの matching page または sheet の budget を使い切ったため、さらに matching place が存在します。
partialCoveragescope 内の一部 context に保存済み text がありません。件数は unscannedContextCount が示します。
truncatedContentscope 内の一部 text は ingestion 時に切り詰められ、検索不可能でした。truncatedContentFileNames は影響を受けた file を sample します。
coverageUnknownscan は成功しましたが、scope のうちどの程度に保存済み text があるかを判断できませんでした。

個別の truncated flag は、返された list が maxMatches で停止し、さらに match が存在することだけを意味します。

knowledge base に接続された agent は、この scan を grepKnowledgeBase tool として取得します。実行時には status updateを broadcast します。grepKnowledgeBase は ranked retrieval の Accessing Knowledge Base title とは異なり、Searching Knowledge Base Text title を報告します。

grep() は TypeScript client で利用できます。Python または REST の equivalent はありません。

Bulk Ingestion​

upsertContexts() は inline で ingestion を行い、context が searchable になると resolve するため、数十 document に適しています。数千 document には、AI provider の batch API を通じて context を実行する durable asynchronous lane である bulk ingestion を使用します。

重要な違いは return contract です。bulkUpsertContexts() は ingestion の完了時ではなく、request がstaged された時点で resolve するため、返された job を別途追跡します。

CLI で Directory を Ingest する​

最も速い方法は CLI です。directory を走査し、file を batch 化して upload し、各 job を完了まで poll します。

squid kb-upload --dir ./docs --knowledgeBase banking-knowledgebase
Option説明
--dirRequired。recursively 走査する local directory。
--knowledgeBaseRequired。ingest 先の knowledge base。
--extensionscomma-separated allow-list。default は pdf、docx、txt、md、html、csv、xlsx、xls、xlsm、xlsb、pptx。
--batchSizejob ごとに stage する file 数。default は 200、最大 1000。
--dryRunupload 対象の file を list 化し、server に接続せずに終了します。
--timeoutMinutesserver-side で引き続き実行中として報告して次へ進むまでに、各 job を待機する時間。default は 120。

--appId、--apiKey、--region、--environmentId は、SQUID_APP_ID、SQUID_API_KEY、SQUID_REGION、SQUID_ENVIRONMENT_ID に fallback します。Ctrl-C を押すと in-flight job が cancel されます。

Code から Context を Stage する​

bulk ingestion には API key が必要なため、backend code から実行してください。

Backend code
const { jobId, contextIds, duplicates } = await this.squid
.ai()
.knowledgeBase('banking-knowledgebase')
.bulkUpsertContexts(contexts, files);

contextIds は渡した context と index-aligned です。content duplicate として拒否された context も slot を占有するため、実際に stage されたものを確認するには context ID によって duplicates を cross-reference します。duplicate は、knowledge base がすでに保持する content、または同じ call 内の前の context が追加した content です。

duplicates は text context と、call に byte を渡した file を対象とします。これらは staging 時点で手元にあるためです。stagedObjectKey により stage された file は例外です。その byte は deferred extraction pass により最初に読み取られるため、duplicate は後で job の per-file status に errorCode: 'DUPLICATE_CONTENT' を持つ failed file として表面化します。knowledge base はすでに content を保持しているため、この code は failure ではなく skip として扱います。通常の failure には errorCode はありません。

Job の追跡​

Client code
const kb = squid.ai().knowledgeBase('banking-knowledgebase');

// Poll for the job's current state.
const status = await kb.getBulkIngestionJob(jobId);
console.log(status.state, status.counts);

// Or subscribe to server-side updates.
kb.observeBulkIngestionJob(jobId).subscribe((update) => {
console.log(update.state, update.counts);
});

// Already-finalized contexts are kept when a job is cancelled.
await kb.cancelBulkIngestionJob(jobId);

observeBulkIngestionJob() は、job が completed、failed、cancelled に達すると complete します。terminal の failed または cancelled state は error ではなく通常の emitted value として届くため、next callback で処理してください。observable が error になるのは transport failure の場合だけです。

計画時に考慮すべき 2 つの detail:

  • observable は cold であるため、subscription ごとに独自の server-side subscription が登録されます。複数 consumer が 1 job を監視する場合は、たとえば RxJS の share() で共有してください。
  • application または knowledge base が job の実行中に削除されると、job record は final update なしで purge され、observable は complete しません。この可能性がある場合は RxJS の timeout() で制限してください。

Large File Set の Upload​

file を直接 bulkUpsertContexts() に渡すと Squid を通じて送信され、request が memory 内で buffer されます。そのため、1 回の call は 50 file、合計 256 MB に制限されます。それを超える場合は presigned URL を発行して storage に直接 upload します。この方法にはどちらの上限もありません。

Backend code
const kb = this.squid.ai().knowledgeBase('banking-knowledgebase');

// At most 500 file names per call.
const { uploads } = await kb.createBulkUploadUrls(['statement-2026-01.pdf', 'statement-2026-02.pdf']);

for (const upload of uploads) {
await fetch(upload.uploadUrl, {
method: 'PUT',
body: fileBytesFor(upload.fileName),
// Required headers are empty on S3, but Azure Blob rejects the PUT without them.
headers: upload.requiredHeaders,
});
}

// Reference the staged objects instead of sending bytes through Squid.
const staged = uploads.map(upload => ({
type: 'file' as const,
contextId: upload.fileName,
stagedObjectKey: upload.stagedObjectKey,
}));
await kb.bulkUpsertContexts(staged);

presigned URL は発行後すぐに expire するため、すべてを先に発行するのではなく、各 wave を速やかに upload してください。

ベストプラクティス​

  • large document は topic ごとに focused な knowledge base に分割します。これにより agent が適切な context を選ぶための signal が向上します。
  • query 時の filtering を有効にし、response 内の noise を削減するため、context に metadata を追加します。