This guide is for an engineer who is giving an Amazon Bedrock application company signals and has to choose between a knowledge base and a tool call. Announcement text suits a knowledge base. Dated rows with a source and an observation time, which is the form of every Fokals dataset, suit a tool that runs a fixed query and returns the rows. The guide sets out what the AWS documentation says each route does today, a worked tool definition and loop, and the checks that keep an answer dated and cited. Fokals is delivered direct, by REST API and as bulk files, which you load into your own storage or call from your own code, and the tool or knowledge base documents in this guide are built on that copy.
What the documentation says today
On 4 October 2026 the Amazon Bedrock documentation describes three routes that matter here. Knowledge bases implement retrieval-augmented generation: documents from sources such as Amazon S3, Confluence, SharePoint or a web crawler are parsed, split into chunks, embedded and stored in a vector store, and at query time the question is converted to a vector and the most similar chunks are returned. Retrieve returns the chunks, and RetrieveAndGenerate also writes an answer with citations to them. The documentation now recommends a Bedrock Managed Knowledge Base, in which Bedrock runs ingestion, storage, indexing and retrieval, over a customer-managed one in which you provision the vector store.
A knowledge base can also connect to a structured data store. For Amazon Redshift and the AWS Glue Data Catalog the documentation says Bedrock uses the Redshift query engine and converts a natural-language question into SQL from the schema, the query history and the query patterns, and GenerateQuery returns that SQL without running it. The query settings for chunks, search type and metadata filters apply only to unstructured sources. The page on setting up the query engine treats arbitrary generated SQL as a security risk for any text-to-SQL application and advises limiting the role to read access, using read-only databases or sandboxing.
Tool use is the third route. With the Converse API you send tool definitions as a JSON schema, the model replies with a request to use a tool, your code runs it and returns a result, and the model answers from that result. Bedrock also offers server-side tool use on the Responses API, where Bedrock calls a Lambda function or an Amazon Bedrock AgentCore Gateway that you registered. The documentation also says that Amazon Bedrock Agents, now called Agents Classic, no longer accepts new customers, and it points to Amazon Bedrock AgentCore for similar capabilities.
Which route answers which question
| Question | Route | What comes back |
|---|---|---|
| What has this company announced since 1 September? | Tool over Company News (company_news) | Rows with at, title, url and event_types |
| How do these companies describe their expansion plans? | Knowledge base over announcement text | Chunks of title and excerpt |
| Which companies on my list raised intent on a topic this week? | Tool over Intent Scores (company_intent_weekly) | Rows where surge is set, with evidence |
| How many data science roles is this company hiring for? | Tool over Hiring Activity (company_hiring_daily) | One row, with by_function |
| Open questions across several tables | Knowledge base on a structured store | SQL that Bedrock writes, for you to review |
The split follows the shape of the answer. An answer in the wording of a passage comes from retrieval by similarity. An answer that is a row, a count or a date range comes from a query. A tool runs the query you wrote, with the arguments the model fills in, so the result matches the table exactly. A knowledge base on a structured store sits between the two, because the model writes the SQL from your schema: use it where the questions are open, and test the generated SQL before you rely on it.
A tool over your own copy of the data
A tool is a schema and a function you write. The model chooses the tool and fills in its arguments, and your code runs one fixed, parameterised query against the copy you loaded into Amazon Redshift or Athena, so the model cannot ask for a table or column you did not expose. In practice a lookup tool comes first, because the user names a company, and your code resolves the name to a company ID, a domain or a ticker. This definition then exposes the announcements of one company since a date.
{
"tools": [
{
"toolSpec": {
"name": "recent_company_events",
"description": "Announcements a company made about itself since a date, newest first, each with the address of the original.",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"company_id": {"type": "string", "description": "The Fokals company_id of the company."},
"since": {"type": "string", "description": "A date such as 2026-09-01."}
},
"required": ["company_id", "since"]
}
}
}
}
]
}The function behind it runs this query, with the two arguments as parameters:
select "at", source, title, url, event_types
from company_news
where company_id = :company_id
and "at" >= :since
order by "at" desc
limit 20;The loop that joins them follows the pattern in the AWS documentation for client-side tool use: call converse, and while the stop reason is tool_use, run each requested tool and send a toolResult back.
import boto3
runtime = boto3.client("bedrock-runtime")
def ask(question, tool_config, run_tool, model_id, max_turns=5):
messages = [{"role": "user", "content": [{"text": question}]}]
for _ in range(max_turns):
reply = runtime.converse(modelId=model_id, messages=messages, toolConfig=tool_config)
message = reply["output"]["message"]
messages.append(message)
if reply["stopReason"] != "tool_use":
return message
results = []
for block in message["content"]:
if "toolUse" in block:
use = block["toolUse"]
rows = run_tool(use["name"], use["input"]) # plain dicts, dates as ISO text
results.append({"toolResult": {"toolUseId": use["toolUseId"], "content": [{"json": {"rows": rows}}]}})
messages.append({"role": "user", "content": results})
raise RuntimeError("The model kept asking for tools")Return the fields that let an answer be checked: the date at, the source and the url of the original announcement. These illustrative rows for Acme Robotics show the shape of a result:
{"rows": [
{"at": "2026-09-24", "source": "page", "title": "Acme Robotics opens a service centre in Rotterdam", "url": "https://www.example.com/news/rotterdam", "event_types": ["expansion"]},
{"at": "2026-09-09", "source": "rss", "title": "Acme Robotics launches the Atlas picker", "url": "https://www.example.com/news/atlas", "event_types": ["product_launch"]}
]}From rows like these the model can write that Acme Robotics published two announcements since 1 September, name their dates and event types, and give the addresses. For an intent score return score, surge and the evidence list, whose entries carry a date, a kind, a source and a weight. Keep each call small. The Fokals API limits each key by minute and by day, so a loop that calls it once for every company can reach those limits. Answer broad questions from your own copy, and keep the API for single lookups.
A second tool, for hiring, shows how to keep no data apart from zero. It reads the latest closed day for one company:
select day, open_postings, new_postings, closed_postings, by_function
from company_hiring_daily
where company_id = :company_id
order by day desc
limit 1;When the query returns nothing, the function returns an empty list with the message that no hiring rows exist for the company, and the system prompt tells the model to repeat it.
Keep every answer dated and honest
Put the properties of the data into the system prompt, because the model does not know them. These lines restate what the methodology and the data dictionary say.
Use only the rows the tools return, and give the date and source address of every fact.
If a tool returns no rows, say that no rows were returned for that company.
Every intent score carries the dated signals behind it: quote them with their dates.
A leadership change is recorded by role and never by the name of a person.Two points belong in the code and not in the prompt. Daily and weekly rows are written once after the period closes, so the newest day in a table is a closed day: return it with the answer as the as-of date, and return the week with an intent score. And a company with no row in Hiring Activity has no hiring rows, so the tool should say that, because zero open postings and an empty result are different facts.
Log each tool call, its arguments and the rows it returned beside the final answer. Because daily and weekly rows are not revised after they are written, an answer given on one date can be checked later against the same rows, which is what point-in-time data makes possible.
When a knowledge base is the right route
For the text of announcements a knowledge base fits. Write one text file for each item in Company News from its title and excerpt, which holds at most 1,200 characters of the company's own text, and put a .metadata.json file beside it in S3. Keep the company ID, the ticker and the source as strings and the date as a number such as 20261003, because the greater-than and less-than filters take numbers, and keep each metadata file under 10 KB, as the S3 connector page requires.
Sync the knowledge base after each daily load, because the documentation says changes reach it only when you sync. Everything synced is available to anyone with bedrock:Retrieve permission, so scope that permission to the licence you hold. Fokals is licensed by written agreement for internal use, embedding in a product or redistribution, and an assistant that shows rows to your customers is not internal use.
Where this stops
Fokals data is company-level: a leadership change is recorded by the role concerned and the date it was observed. Company announcements and regulatory disclosures are classified into 13 event types under named, frozen versions, so show them as signals with their dates and sources, and link the original. The guide to company data as context for AI agents and the guide to retrieval over structured company signals cover the same design away from Amazon Bedrock.
Frequently asked questions
Should I use an Amazon Bedrock knowledge base or tool use for structured data?
Use a knowledge base when the answer is in passages of text, and a tool call when the answer is a row. A knowledge base on a structured store lets Bedrock write the SQL from your schema, while a tool runs a query you wrote with arguments the model fills in. Choose the tool when the same few questions recur and the result must match the table exactly. Choose the knowledge base for open questions, and test the SQL it generates.
Can an Amazon Bedrock knowledge base query a SQL database?
Yes, for data in Amazon Redshift or the AWS Glue Data Catalog, through the Redshift query engine, which converts a question into SQL using your schema metadata. Grant the service role SELECT only, because the documentation treats arbitrary generated SQL as a security risk and advises read access, read-only databases or sandboxing. The settings for chunks and metadata filters do not apply to structured stores.
How do I make an Amazon Bedrock answer cite its sources?
With a knowledge base, RetrieveAndGenerate returns citations to the source chunks. With tool use, return the source and its date in every row and tell the model to quote them. Fokals rows carry their source and the time they were observed, the source link of a Company News item points to the original announcement, and the evidence of an intent score gives its five strongest signals with dates and sources.
How do I use Fokals data in an Amazon Bedrock application?
Fokals is delivered direct, by REST API and as bulk files. Load the files into your own storage, or call the API from your own code, and build a tool that runs a fixed query over the copy, or knowledge base documents from the announcement text, as described here. Each row carries its source and the time it was observed, so every answer can be dated and cited.
Does Amazon Bedrock Agents still accept new customers?
The Amazon Bedrock documentation says that Amazon Bedrock Agents, now called Amazon Bedrock Agents Classic, no longer accepts new customers, that existing customers can continue to use it, and that Amazon Bedrock AgentCore offers similar capabilities. AgentCore Gateway converts APIs, Lambda functions and existing services into Model Context Protocol tools, so a function that queries your company tables can be offered to an agent that way. The guide to company data over Model Context Protocol covers the wrapper.
The queries and code on this page are examples to adapt. Test them in your own environment before you rely on them.
What this page says about the products it names was checked against their public documentation on 4 October 2026. Product and company names are trademarks of their owners. Fokals is not affiliated with them or endorsed by them.