'perform chat research' script command - very impressive

Hi all,

I’m learning a bit about the new ‘perform chat research’ command in 4.2.2. This is quite something. I had Gemini build an AppleScript that uses this new command, and the results so far seem quite impressive.

What I find interesting is that it is not actually reading the contents of, in my particular case, my journal articles database. Instead, as near as I can figure (based on how Gemini is explaining it to me) it is looking for specific strings of text and has DEVONthink generate an ‘abstract’ that is then synthesised in some output that leverages whichever AI tool you’ve selected in Preferences.

Still learning about what this does, and I’m still playing around with the full Apple Script itself, but just wanted to flag it here for others’ benefit.

You asked Gemini to write an AppleScript where…?

The command is basically what the chat assistant (and likewise the Chat - Query smart action and the get chat response for message AppleScript command) uses when researching one or more sources, therefore the Web & Wikipedia options in Settings > AI > Search matter too. And the default AI provider (see Settings > AI > Chat) is used to filter the results.

However, so far the snippets/abstracts are generated by DEVONthink, not by external AI, as the main use case for these results is to use them in additional AI requests (just like the chat assistant doesn’t present the raw results but instead uses the search results to build the response)

In case that anyone’s interested I could provide an example script…

Thanks Christian - yes, would love to see an example script.

Jim: right now, the script just lives in the DT script menu.

The promised example:

-- Research Report

tell application id "DNtp"
	show progress indicator "Research Report"
	try
		set theReviewMessage to "Enter the research topic:"
		try
			set theReviewResult to display dialog theReviewMessage buttons {"Reject", "Approve"} default button "Approve" with title "Research Report" default answer ""
			set theUserResponse to text returned of theReviewResult
			set theButtonPressed to button returned of theReviewResult
			
			if theButtonPressed is "Approve" then
				set theSources to {"web"}
				set theResearchQuery to theUserResponse
				set ctx_research to ""
				try
					set ctx_research to perform chat research theResearchQuery sources theSources maximum results 10
				end try
				set theNormalized to {}
				repeat with r in ctx_research
					set theText to text content of r
					if theText is "" then set theText to abstract of r
					set end of theNormalized to {|title|:title of r, |link|:URL of r, |authors|:authors of r, |text|:theText, |abstract|:abstract of r}
				end repeat
				set ctx_research to theNormalized
			end if
		end try
		
		set theEntriesList to {}
		repeat with r in ctx_research
			set ctx_title to |title| of r
			set ctx_link to |link| of r
			set ctx_authors to |authors| of r
			set ctx_text to |text| of r
			set ctx_abstract to |abstract| of r
			set end of theEntriesList to "### " & ctx_title & "" & return & "" & ctx_text & "" & return & "[Source](" & ctx_link & ")"
		end repeat
		
		if (count of theEntriesList) is 0 then error
		
		set ctx_report to "# Research Report" & return & "" & return & "" & my joinList(theEntriesList, linefeed & linefeed) & "" & return & ""
		set ctx_polished to ""
		set theGenPrompt to "<report>" & ctx_report & "</report>"
		set theGenRole to "You are a research editor. Rewrite the following collected research into a polished, well-structured Markdown report. Preserve all source links and key facts. Organise under clear section headings."
		try
			set theGenResult to get chat response for message theGenPrompt role theGenRole
			if theGenResult is not missing value then set ctx_polished to theGenResult
		end try
		
		set theDocName to theUserResponse
		set theDocContent to ctx_polished
		set theTargetDB to current database
		set theTargetGroup to create location "/Research" in theTargetDB
		set theRecord to create record with {name:theDocName, type:markdown, content:theDocContent} in theTargetGroup
	end try
	hide progress indicator
end tell

on joinList(theList, theDelimiter)
	set oldDelims to AppleScript's text item delimiters
	set AppleScript's text item delimiters to theDelimiter
	set theResult to theList as string
	set AppleScript's text item delimiters to oldDelims
	return theResult
end joinList

P.S: Automatically generated and only slightly polished but fully functional.
P.P.S: But it’s not AI generated, @chrillek :wink:

6 Likes

Thanks Christian!

Apologies for resurrecting this, but quick question: is there a hard limit of the number of items queried when using ‘perform chat research’? When deploying a script, I seem to top out at 32.

Here is the script:

tell application id "DNtp"
	try
		-- Step 1: Query dialog
		display dialog "Enter your research query:" default answer "" with title "Quick Query"
		set searchKeywords to text returned of result

		-- Step 2: Target destination
		set targetDestination to incoming group

		-- Step 3: Search DEVONthink
		show progress indicator "Quick Query" steps 4
		step progress indicator "Searching DEVONthink..."
		set researchResults to perform chat research searchKeywords sources {"databases"} maximum results 120

		-- Handle empty results
		if researchResults is missing value or (count of researchResults) = 0 then
			hide progress indicator
			display alert "No relevant fragments found." message "Try a different query." as warning
			return
		end if

		-- Step 4: Build fragment text and reference map
		step progress indicator "Processing fragments..."
		set collectiveSnippets to ""
		set refMap to ""
		set refTableRows to ""
		set refCounter to 0

		repeat with aResult in researchResults
			set theUUID to URL of aResult
			set theRecord to get record with uuid theUUID
			set theTitle to name of theRecord

			set refCounter to refCounter + 1
			set currentRefID to "REF-" & refCounter

			-- Get text content
			set usedText to ""
			try
				set usedText to plain text of theRecord
			end try

			-- Build collective snippets fragment
			if usedText is not "" then
				set collectiveSnippets to collectiveSnippets & "<fragment id='" & currentRefID & "'>" & return & "DOCUMENT: " & theTitle & return & "CONTENT: " & usedText & return & "</fragment>" & return
			end if

			-- Build reference map (REF-N | x-devonthink-item://UUID | Title)
			set refMap to refMap & currentRefID & " | " & theUUID & " | " & theTitle & return

			-- Build reference table row
			set refTableRows to refTableRows & "<tr><td style='padding: 8px;'><a href='" & theUUID & "'>" & currentRefID & "</a></td><td style='padding: 8px;'>" & theTitle & "</td></tr>" & return
		end repeat

		-- Step 5: Build prompts and call AI
		step progress indicator "Querying AI..."
		set systemRole to "You are a concise research assistant. Using ONLY the provided document fragments, organize your entire response by document. For EACH document that contains content relevant to the research question, output a section (skip any document with no relevant content — do not mention skipped documents). For each relevant document, output in this exact order: (1) an <h2> subheading formatted exactly as: <h2><a href=" & quote & "x-devonthink-item://UUID" & quote & ">REF-N</a>: Document Title</h2> — look up the UUID and title from the REFERENCE MAP; (2) two to three <p> paragraphs that summarise what this specific document says in relation to the research query — the summary must directly address the query topic first (e.g. if the query is 'Bermuda 1', begin by explaining what the document says about Bermuda 1 specifically) and then convey the document's broader relevant argument or findings — be detailed and specific to the document's actual content — do not use verbatim passages or quotations; (3) a <ul> list with as many <li> items as needed that summarises the key points of this document (not limited to the query — cover the document's main findings and arguments). Do not invent information. Do not merge or synthesize content across documents. Use only <h2>, <p>, <ul>, and <li> HTML tags (no <html>, <head>, <body>, or <blockquote> tags)."

		set userMessage to "QUERY: " & searchKeywords & return & return & "REFERENCE MAP:" & return & refMap & return & "<data>" & return & collectiveSnippets & "</data>"

		set masterAnswer to get chat response for message userMessage role systemRole temperature 0.3 thinking false tool calls false

		-- Step 6: Get current date
		set theDate to current date
		set theDay to day of theDate as text
		set theMonth to (month of theDate as integer) as text
		set theYear to year of theDate as text
		set dateString to theDay & "/" & theMonth & "/" & theYear

		-- Step 7: Assemble final HTML
		step progress indicator "Building document..."
		set finalHTML to "<html><head><style>h2 { font-size: 14pt; margin-top: 24px; padding-bottom: 4px; border-bottom: 1px dotted #aaa; }</style></head><body style='font-family: Helvetica; font-size: 16pt; line-height: 1.5; max-width: 800px; margin: 20px;'>" & return
		set finalHTML to finalHTML & "<h1 style='font-size: 18pt; text-transform: uppercase; border-bottom: 1px solid #ccc;'>" & searchKeywords & "</h1>" & return
		set finalHTML to finalHTML & "<p style='font-size: 10pt; color: #666;'>Quick Query - " & dateString & " - " & refCounter & " sources</p>" & return
		set finalHTML to finalHTML & masterAnswer & return
		set finalHTML to finalHTML & "<hr>" & return
		set finalHTML to finalHTML & "<h2 style='font-size: 13pt;'>References</h2>" & return
		set finalHTML to finalHTML & "<table border='1' style='width: 100%; border-collapse: collapse;'>" & return
		set finalHTML to finalHTML & "<tr><th style='padding: 8px; width: 15%;'>ID</th><th style='padding: 8px;'>Document</th></tr>" & return
		set finalHTML to finalHTML & refTableRows
		set finalHTML to finalHTML & "</table>" & return
		set finalHTML to finalHTML & "</body></html>"

		-- Step 8: Create DEVONthink note
		set theNote to create record with {name: searchKeywords & " (Quick Query)", type: HTML, content: finalHTML} in targetDestination

		hide progress indicator
		open tab for record theNote

	on error error_message number error_number
		hide progress indicator
		if error_number is not -128 then
			display alert "Error" message error_message buttons {"OK"} default button 1
		end if
	end try
end tell

There are indeed limits which vary depending on the usage mode and the used AI model and search engine (which have their own limits).

Thanks Christian. I’m hitting an internal (database) source limit of 32 regardless of the model selected.

Is the hard limit thus inside the ‘perform chat research’ command? Is it possible to have an option to increase this?

It is. Depending on the usage mode it’s lower or higher as the AI requests cause additional costs. The main purpose of this command is to feed the results into additional AI requests (just like in the chat assistant or in my example above).

1 Like