interactions: - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '108' content-type: - application/json host: - localhost:11434 method: POST parsed_body: encoding_format: base64 input: - 'Sales report Q1: Revenue was $100,000.' model: qwen3-embedding:4b uri: http://localhost:11434/v1/embeddings response: headers: content-type: - application/json transfer-encoding: - chunked parsed_body: data: - embedding: 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 index: 0 object: embedding model: qwen3-embedding:4b object: list usage: prompt_tokens: 17 total_tokens: 17 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '108' content-type: - application/json host: - localhost:11434 method: POST parsed_body: encoding_format: base64 input: - 'Sales report Q2: Revenue was $150,000.' model: qwen3-embedding:4b uri: http://localhost:11434/v1/embeddings response: headers: content-type: - application/json transfer-encoding: - chunked parsed_body: data: - embedding: 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 index: 0 object: embedding model: qwen3-embedding:4b object: list usage: prompt_tokens: 17 total_tokens: 17 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '108' content-type: - application/json host: - localhost:11434 method: POST parsed_body: encoding_format: base64 input: - 'Sales report Q3: Revenue was $200,000.' model: qwen3-embedding:4b uri: http://localhost:11434/v1/embeddings response: headers: content-type: - application/json transfer-encoding: - chunked parsed_body: data: - embedding: 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 index: 0 object: embedding model: qwen3-embedding:4b object: list usage: prompt_tokens: 17 total_tokens: 17 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '7702' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### ask(question) -> str Ask a question using the QA agent with RAG. Returns the answer as a string. Use this for semantic analysis that benefits from LLM reasoning. ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use ask() for Semantic Analysis**: When you need to understand meaning or interpret content, use the ask() function. 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using ask() for semantic analysis ```python # First search to find relevant content results = search("machine learning approaches") # Then use ask() to synthesize an answer summary = ask("What are the main machine learning approaches discussed?") print(summary) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: What is the total revenue across all quarterly reports? role: user model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '695' content-type: - application/json parsed_body: choices: - finish_reason: tool_calls index: 0 message: content: '' reasoning: We need revenue from quarterly reports. Search for "quarterly report" and revenue. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"quarterly report revenue\", limit=50)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''], r[''page_numbers''])\n"}' name: execute_code id: call_8cd1wnf6 index: 0 type: function created: 1769703355 id: chatcmpl-273 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 87 prompt_tokens: 1601 total_tokens: 1688 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '94' content-type: - application/json host: - localhost:11434 method: POST parsed_body: encoding_format: base64 input: - quarterly report revenue model: qwen3-embedding:4b uri: http://localhost:11434/v1/embeddings response: headers: content-type: - application/json transfer-encoding: - chunked parsed_body: data: - embedding: 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 index: 0 object: embedding model: qwen3-embedding:4b object: list usage: prompt_tokens: 5 total_tokens: 5 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '8540' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### ask(question) -> str Ask a question using the QA agent with RAG. Returns the answer as a string. Use this for semantic analysis that benefits from LLM reasoning. ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use ask() for Semantic Analysis**: When you need to understand meaning or interpret content, use the ask() function. 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using ask() for semantic analysis ```python # First search to find relevant content results = search("machine learning approaches") # Then use ask() to synthesize an answer summary = ask("What are the main machine learning approaches discussed?") print(summary) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: What is the total revenue across all quarterly reports? role: user - content: |- We need revenue from quarterly reports. Search for "quarterly report" and revenue. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"quarterly report revenue\", limit=50)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''], r[''page_numbers''])\n"}' name: execute_code id: call_8cd1wnf6 type: function - content: '{"code":"results = search(\"quarterly report revenue\", limit=50)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''], r[''page_numbers''])\n","stdout":"3\nQ1 Report 0.03226645663380623 []\nQ2 Report 0.03226645663380623 []\nQ3 Report 0.032258063554763794 []\n","stderr":"","success":true}' role: tool tool_call_id: call_8cd1wnf6 model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '635' content-type: - application/json parsed_body: choices: - finish_reason: tool_calls index: 0 message: content: '' reasoning: 'We have 3 reports: Q1, Q2, Q3. Likely Q4 also exists. Search again for Q4.' role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"Q4 Report\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n"}' name: execute_code id: call_mgo4t2ty index: 0 type: function created: 1769703357 id: chatcmpl-775 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 85 prompt_tokens: 1812 total_tokens: 1897 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '79' content-type: - application/json host: - localhost:11434 method: POST parsed_body: encoding_format: base64 input: - Q4 Report model: qwen3-embedding:4b uri: http://localhost:11434/v1/embeddings response: headers: content-type: - application/json transfer-encoding: - chunked parsed_body: data: - embedding: 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 index: 0 object: embedding model: qwen3-embedding:4b object: list usage: prompt_tokens: 4 total_tokens: 4 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '9198' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### ask(question) -> str Ask a question using the QA agent with RAG. Returns the answer as a string. Use this for semantic analysis that benefits from LLM reasoning. ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use ask() for Semantic Analysis**: When you need to understand meaning or interpret content, use the ask() function. 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using ask() for semantic analysis ```python # First search to find relevant content results = search("machine learning approaches") # Then use ask() to synthesize an answer summary = ask("What are the main machine learning approaches discussed?") print(summary) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: What is the total revenue across all quarterly reports? role: user - content: |- We need revenue from quarterly reports. Search for "quarterly report" and revenue. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"quarterly report revenue\", limit=50)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''], r[''page_numbers''])\n"}' name: execute_code id: call_8cd1wnf6 type: function - content: '{"code":"results = search(\"quarterly report revenue\", limit=50)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''], r[''page_numbers''])\n","stdout":"3\nQ1 Report 0.03226645663380623 []\nQ2 Report 0.03226645663380623 []\nQ3 Report 0.032258063554763794 []\n","stderr":"","success":true}' role: tool tool_call_id: call_8cd1wnf6 - content: |- We have 3 reports: Q1, Q2, Q3. Likely Q4 also exists. Search again for Q4. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"Q4 Report\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n"}' name: execute_code id: call_mgo4t2ty type: function - content: '{"code":"results = search(\"Q4 Report\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n","stdout":"3\nQ1 Report\nQ2 Report\nQ3 Report\n","stderr":"","success":true}' role: tool tool_call_id: call_mgo4t2ty model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '663' content-type: - application/json parsed_body: choices: - finish_reason: tool_calls index: 0 message: content: '' reasoning: All quarterly reports 1-3 only? Maybe Q4 is in separate doc. Search “Quarterly Report 4”. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"Quarterly Report 4\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n"}' name: execute_code id: call_3d3jutqn index: 0 type: function created: 1769703359 id: chatcmpl-718 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 84 prompt_tokens: 1975 total_tokens: 2059 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '88' content-type: - application/json host: - localhost:11434 method: POST parsed_body: encoding_format: base64 input: - Quarterly Report 4 model: qwen3-embedding:4b uri: http://localhost:11434/v1/embeddings response: headers: content-type: - application/json transfer-encoding: - chunked parsed_body: data: - embedding: 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 index: 0 object: embedding model: qwen3-embedding:4b object: list usage: prompt_tokens: 6 total_tokens: 6 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '9893' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### ask(question) -> str Ask a question using the QA agent with RAG. Returns the answer as a string. Use this for semantic analysis that benefits from LLM reasoning. ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use ask() for Semantic Analysis**: When you need to understand meaning or interpret content, use the ask() function. 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using ask() for semantic analysis ```python # First search to find relevant content results = search("machine learning approaches") # Then use ask() to synthesize an answer summary = ask("What are the main machine learning approaches discussed?") print(summary) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: What is the total revenue across all quarterly reports? role: user - content: |- We need revenue from quarterly reports. Search for "quarterly report" and revenue. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"quarterly report revenue\", limit=50)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''], r[''page_numbers''])\n"}' name: execute_code id: call_8cd1wnf6 type: function - content: '{"code":"results = search(\"quarterly report revenue\", limit=50)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''], r[''page_numbers''])\n","stdout":"3\nQ1 Report 0.03226645663380623 []\nQ2 Report 0.03226645663380623 []\nQ3 Report 0.032258063554763794 []\n","stderr":"","success":true}' role: tool tool_call_id: call_8cd1wnf6 - content: |- We have 3 reports: Q1, Q2, Q3. Likely Q4 also exists. Search again for Q4. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"Q4 Report\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n"}' name: execute_code id: call_mgo4t2ty type: function - content: '{"code":"results = search(\"Q4 Report\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n","stdout":"3\nQ1 Report\nQ2 Report\nQ3 Report\n","stderr":"","success":true}' role: tool tool_call_id: call_mgo4t2ty - content: |- All quarterly reports 1-3 only? Maybe Q4 is in separate doc. Search “Quarterly Report 4”. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"Quarterly Report 4\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n"}' name: execute_code id: call_3d3jutqn type: function - content: '{"code":"results = search(\"Quarterly Report 4\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n","stdout":"3\nQ1 Report\nQ2 Report\nQ3 Report\n","stderr":"","success":true}' role: tool tool_call_id: call_3d3jutqn model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '1144' content-type: - application/json parsed_body: choices: - finish_reason: tool_calls index: 0 message: content: |- It appears only Q1‑Q3 reports are present in the index. We need revenue figures from each. We'll retrieve the full text of each report and extract numbers labeled “Revenue”. role: assistant tool_calls: - function: arguments: '{"code":"docs = [''Q1 Report'', ''Q2 Report'', ''Q3 Report'']\nrevenues = {}\nimport re\nfor d in docs:\n content = get_document(d)\n if content:\n # Find revenue lines\n matches = re.findall(r''Revenue.*?:\\s*\\$([\\d,\\.]+)'', content, re.IGNORECASE)\n if matches:\n # take first match\n rev = float(matches[0].replace('','',''''))\n revenues[d] = rev\n else:\n revenues[d] = None\n else:\n revenues[d] = None\nprint(revenues)\n"}' name: execute_code id: call_2rg8jz4m index: 0 type: function created: 1769703364 id: chatcmpl-874 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 204 prompt_tokens: 2139 total_tokens: 2343 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '11457' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### ask(question) -> str Ask a question using the QA agent with RAG. Returns the answer as a string. Use this for semantic analysis that benefits from LLM reasoning. ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use ask() for Semantic Analysis**: When you need to understand meaning or interpret content, use the ask() function. 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using ask() for semantic analysis ```python # First search to find relevant content results = search("machine learning approaches") # Then use ask() to synthesize an answer summary = ask("What are the main machine learning approaches discussed?") print(summary) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: What is the total revenue across all quarterly reports? role: user - content: |- We need revenue from quarterly reports. Search for "quarterly report" and revenue. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"quarterly report revenue\", limit=50)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''], r[''page_numbers''])\n"}' name: execute_code id: call_8cd1wnf6 type: function - content: '{"code":"results = search(\"quarterly report revenue\", limit=50)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''], r[''page_numbers''])\n","stdout":"3\nQ1 Report 0.03226645663380623 []\nQ2 Report 0.03226645663380623 []\nQ3 Report 0.032258063554763794 []\n","stderr":"","success":true}' role: tool tool_call_id: call_8cd1wnf6 - content: |- We have 3 reports: Q1, Q2, Q3. Likely Q4 also exists. Search again for Q4. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"Q4 Report\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n"}' name: execute_code id: call_mgo4t2ty type: function - content: '{"code":"results = search(\"Q4 Report\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n","stdout":"3\nQ1 Report\nQ2 Report\nQ3 Report\n","stderr":"","success":true}' role: tool tool_call_id: call_mgo4t2ty - content: |- All quarterly reports 1-3 only? Maybe Q4 is in separate doc. Search “Quarterly Report 4”. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"Quarterly Report 4\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n"}' name: execute_code id: call_3d3jutqn type: function - content: '{"code":"results = search(\"Quarterly Report 4\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n","stdout":"3\nQ1 Report\nQ2 Report\nQ3 Report\n","stderr":"","success":true}' role: tool tool_call_id: call_3d3jutqn - content: |2- It appears only Q1‑Q3 reports are present in the index. We need revenue figures from each. We'll retrieve the full text of each report and extract numbers labeled “Revenue”. role: assistant tool_calls: - function: arguments: '{"code":"docs = [''Q1 Report'', ''Q2 Report'', ''Q3 Report'']\nrevenues = {}\nimport re\nfor d in docs:\n content = get_document(d)\n if content:\n # Find revenue lines\n matches = re.findall(r''Revenue.*?:\\s*\\$([\\d,\\.]+)'', content, re.IGNORECASE)\n if matches:\n # take first match\n rev = float(matches[0].replace('','',''''))\n revenues[d] = rev\n else:\n revenues[d] = None\n else:\n revenues[d] = None\nprint(revenues)\n"}' name: execute_code id: call_2rg8jz4m type: function - content: '{"code":"docs = [''Q1 Report'', ''Q2 Report'', ''Q3 Report'']\nrevenues = {}\nimport re\nfor d in docs:\n content = get_document(d)\n if content:\n # Find revenue lines\n matches = re.findall(r''Revenue.*?:\\s*\\$([\\d,\\.]+)'', content, re.IGNORECASE)\n if matches:\n # take first match\n rev = float(matches[0].replace('','',''''))\n revenues[d] = rev\n else:\n revenues[d] = None\n else:\n revenues[d] = None\nprint(revenues)\n","stdout":"{''Q1 Report'': None, ''Q2 Report'': None, ''Q3 Report'': None}\n","stderr":"","success":true}' role: tool tool_call_id: call_2rg8jz4m model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '558' content-type: - application/json parsed_body: choices: - finish_reason: tool_calls index: 0 message: content: '' reasoning: No revenue found by pattern. Let's inspect content snippet. role: assistant tool_calls: - function: arguments: '{"code":"content = get_document(''Q1 Report'')\nprint(content[:500])\n"}' name: execute_code id: call_oqz8cbe0 index: 0 type: function created: 1769703365 id: chatcmpl-151 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 52 prompt_tokens: 2528 total_tokens: 2580 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '11977' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### ask(question) -> str Ask a question using the QA agent with RAG. Returns the answer as a string. Use this for semantic analysis that benefits from LLM reasoning. ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use ask() for Semantic Analysis**: When you need to understand meaning or interpret content, use the ask() function. 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using ask() for semantic analysis ```python # First search to find relevant content results = search("machine learning approaches") # Then use ask() to synthesize an answer summary = ask("What are the main machine learning approaches discussed?") print(summary) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: What is the total revenue across all quarterly reports? role: user - content: |- We need revenue from quarterly reports. Search for "quarterly report" and revenue. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"quarterly report revenue\", limit=50)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''], r[''page_numbers''])\n"}' name: execute_code id: call_8cd1wnf6 type: function - content: '{"code":"results = search(\"quarterly report revenue\", limit=50)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''], r[''page_numbers''])\n","stdout":"3\nQ1 Report 0.03226645663380623 []\nQ2 Report 0.03226645663380623 []\nQ3 Report 0.032258063554763794 []\n","stderr":"","success":true}' role: tool tool_call_id: call_8cd1wnf6 - content: |- We have 3 reports: Q1, Q2, Q3. Likely Q4 also exists. Search again for Q4. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"Q4 Report\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n"}' name: execute_code id: call_mgo4t2ty type: function - content: '{"code":"results = search(\"Q4 Report\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n","stdout":"3\nQ1 Report\nQ2 Report\nQ3 Report\n","stderr":"","success":true}' role: tool tool_call_id: call_mgo4t2ty - content: |- All quarterly reports 1-3 only? Maybe Q4 is in separate doc. Search “Quarterly Report 4”. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"Quarterly Report 4\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n"}' name: execute_code id: call_3d3jutqn type: function - content: '{"code":"results = search(\"Quarterly Report 4\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n","stdout":"3\nQ1 Report\nQ2 Report\nQ3 Report\n","stderr":"","success":true}' role: tool tool_call_id: call_3d3jutqn - content: |2- It appears only Q1‑Q3 reports are present in the index. We need revenue figures from each. We'll retrieve the full text of each report and extract numbers labeled “Revenue”. role: assistant tool_calls: - function: arguments: '{"code":"docs = [''Q1 Report'', ''Q2 Report'', ''Q3 Report'']\nrevenues = {}\nimport re\nfor d in docs:\n content = get_document(d)\n if content:\n # Find revenue lines\n matches = re.findall(r''Revenue.*?:\\s*\\$([\\d,\\.]+)'', content, re.IGNORECASE)\n if matches:\n # take first match\n rev = float(matches[0].replace('','',''''))\n revenues[d] = rev\n else:\n revenues[d] = None\n else:\n revenues[d] = None\nprint(revenues)\n"}' name: execute_code id: call_2rg8jz4m type: function - content: '{"code":"docs = [''Q1 Report'', ''Q2 Report'', ''Q3 Report'']\nrevenues = {}\nimport re\nfor d in docs:\n content = get_document(d)\n if content:\n # Find revenue lines\n matches = re.findall(r''Revenue.*?:\\s*\\$([\\d,\\.]+)'', content, re.IGNORECASE)\n if matches:\n # take first match\n rev = float(matches[0].replace('','',''''))\n revenues[d] = rev\n else:\n revenues[d] = None\n else:\n revenues[d] = None\nprint(revenues)\n","stdout":"{''Q1 Report'': None, ''Q2 Report'': None, ''Q3 Report'': None}\n","stderr":"","success":true}' role: tool tool_call_id: call_2rg8jz4m - content: |- No revenue found by pattern. Let's inspect content snippet. role: assistant tool_calls: - function: arguments: '{"code":"content = get_document(''Q1 Report'')\nprint(content[:500])\n"}' name: execute_code id: call_oqz8cbe0 type: function - content: '{"code":"content = get_document(''Q1 Report'')\nprint(content[:500])\n","stdout":"Sales report Q1: Revenue was $100,000.\n","stderr":"","success":true}' role: tool tool_call_id: call_oqz8cbe0 model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '855' content-type: - application/json parsed_body: choices: - finish_reason: tool_calls index: 0 message: content: '' reasoning: Need to handle different phrasing. Search for "$" pattern. role: assistant tool_calls: - function: arguments: '{"code":"import re\nrevs={}\nfor d in [''Q1 Report'',''Q2 Report'',''Q3 Report'']:\n content=get_document(d)\n if content:\n vals=re.findall(r''\\$([\\d,]+)'',content)\n if vals:\n rev=sum(int(v.replace('','','''')) for v in vals)\n else:\n rev=None\n else:\n rev=None\n revs[d]=rev\nprint(revs)\n"}' name: execute_code id: call_2j8yqv8s index: 0 type: function created: 1769703369 id: chatcmpl-192 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 139 prompt_tokens: 2641 total_tokens: 2780 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '13113' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### ask(question) -> str Ask a question using the QA agent with RAG. Returns the answer as a string. Use this for semantic analysis that benefits from LLM reasoning. ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use ask() for Semantic Analysis**: When you need to understand meaning or interpret content, use the ask() function. 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using ask() for semantic analysis ```python # First search to find relevant content results = search("machine learning approaches") # Then use ask() to synthesize an answer summary = ask("What are the main machine learning approaches discussed?") print(summary) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: What is the total revenue across all quarterly reports? role: user - content: |- We need revenue from quarterly reports. Search for "quarterly report" and revenue. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"quarterly report revenue\", limit=50)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''], r[''page_numbers''])\n"}' name: execute_code id: call_8cd1wnf6 type: function - content: '{"code":"results = search(\"quarterly report revenue\", limit=50)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''], r[''page_numbers''])\n","stdout":"3\nQ1 Report 0.03226645663380623 []\nQ2 Report 0.03226645663380623 []\nQ3 Report 0.032258063554763794 []\n","stderr":"","success":true}' role: tool tool_call_id: call_8cd1wnf6 - content: |- We have 3 reports: Q1, Q2, Q3. Likely Q4 also exists. Search again for Q4. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"Q4 Report\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n"}' name: execute_code id: call_mgo4t2ty type: function - content: '{"code":"results = search(\"Q4 Report\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n","stdout":"3\nQ1 Report\nQ2 Report\nQ3 Report\n","stderr":"","success":true}' role: tool tool_call_id: call_mgo4t2ty - content: |- All quarterly reports 1-3 only? Maybe Q4 is in separate doc. Search “Quarterly Report 4”. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"Quarterly Report 4\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n"}' name: execute_code id: call_3d3jutqn type: function - content: '{"code":"results = search(\"Quarterly Report 4\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n","stdout":"3\nQ1 Report\nQ2 Report\nQ3 Report\n","stderr":"","success":true}' role: tool tool_call_id: call_3d3jutqn - content: |2- It appears only Q1‑Q3 reports are present in the index. We need revenue figures from each. We'll retrieve the full text of each report and extract numbers labeled “Revenue”. role: assistant tool_calls: - function: arguments: '{"code":"docs = [''Q1 Report'', ''Q2 Report'', ''Q3 Report'']\nrevenues = {}\nimport re\nfor d in docs:\n content = get_document(d)\n if content:\n # Find revenue lines\n matches = re.findall(r''Revenue.*?:\\s*\\$([\\d,\\.]+)'', content, re.IGNORECASE)\n if matches:\n # take first match\n rev = float(matches[0].replace('','',''''))\n revenues[d] = rev\n else:\n revenues[d] = None\n else:\n revenues[d] = None\nprint(revenues)\n"}' name: execute_code id: call_2rg8jz4m type: function - content: '{"code":"docs = [''Q1 Report'', ''Q2 Report'', ''Q3 Report'']\nrevenues = {}\nimport re\nfor d in docs:\n content = get_document(d)\n if content:\n # Find revenue lines\n matches = re.findall(r''Revenue.*?:\\s*\\$([\\d,\\.]+)'', content, re.IGNORECASE)\n if matches:\n # take first match\n rev = float(matches[0].replace('','',''''))\n revenues[d] = rev\n else:\n revenues[d] = None\n else:\n revenues[d] = None\nprint(revenues)\n","stdout":"{''Q1 Report'': None, ''Q2 Report'': None, ''Q3 Report'': None}\n","stderr":"","success":true}' role: tool tool_call_id: call_2rg8jz4m - content: |- No revenue found by pattern. Let's inspect content snippet. role: assistant tool_calls: - function: arguments: '{"code":"content = get_document(''Q1 Report'')\nprint(content[:500])\n"}' name: execute_code id: call_oqz8cbe0 type: function - content: '{"code":"content = get_document(''Q1 Report'')\nprint(content[:500])\n","stdout":"Sales report Q1: Revenue was $100,000.\n","stderr":"","success":true}' role: tool tool_call_id: call_oqz8cbe0 - content: |- Need to handle different phrasing. Search for "$" pattern. role: assistant tool_calls: - function: arguments: '{"code":"import re\nrevs={}\nfor d in [''Q1 Report'',''Q2 Report'',''Q3 Report'']:\n content=get_document(d)\n if content:\n vals=re.findall(r''\\$([\\d,]+)'',content)\n if vals:\n rev=sum(int(v.replace('','','''')) for v in vals)\n else:\n rev=None\n else:\n rev=None\n revs[d]=rev\nprint(revs)\n"}' name: execute_code id: call_2j8yqv8s type: function - content: '{"code":"import re\nrevs={}\nfor d in [''Q1 Report'',''Q2 Report'',''Q3 Report'']:\n content=get_document(d)\n if content:\n vals=re.findall(r''\\$([\\d,]+)'',content)\n if vals:\n rev=sum(int(v.replace('','','''')) for v in vals)\n else:\n rev=None\n else:\n rev=None\n revs[d]=rev\nprint(revs)\n","stdout":"{''Q1 Report'': 100000, ''Q2 Report'': 150000, ''Q3 Report'': 200000}\n","stderr":"","success":true}' role: tool tool_call_id: call_2j8yqv8s model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '995' content-type: - application/json parsed_body: choices: - finish_reason: stop index: 0 message: content: "**Answer**\n\nThe total revenue reported across the three quarterly reports is:\n\n\\- Q1 Report: **$100,000** \ \n\\- Q2 Report: **$150,000** \n\\- Q3 Report: **$200,000**\n\n**Total Revenue (all quarters combined): $450,000**\n\n**Key Findings & Sources**\n\n1. **Q1 Report** – revenue extraction from the text \"Revenue was $100,000.\"\n - Source snippet: *“Sales report Q1: Revenue was $100,000.”*\n2. **Q2 Report** – revenue extracted from \"$150,000\" in the document.\n3. **Q3 Report** – revenue extracted from \"$200,000\" in the document.\n\nAll figures were obtained by searching each document for dollar amounts and summing them. No Q4 report was found in the available documents." role: assistant created: 1769703373 id: chatcmpl-568 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 180 prompt_tokens: 2941 total_tokens: 3121 status: code: 200 message: OK - request: headers: accept: - application/json accept-encoding: - gzip, deflate, zstd connection: - keep-alive content-length: - '14838' content-type: - application/json host: - localhost:11434 method: POST parsed_body: messages: - content: |- You are a Recursive Language Model (RLM) agent that solves complex research questions by writing and executing Python code. IMPORTANT: You MUST use the `execute_code` tool to run Python code. The functions described below are ONLY available inside the execute_code tool - you cannot access them any other way. Always execute code to answer questions; do not just describe what code would do. CRITICAL: Inside execute_code, these functions are ALREADY available in the namespace. Do NOT import them - just use them directly: - search("query") ✓ CORRECT - from haiku.rag import search ✗ WRONG - will fail You have access to a sandboxed Python environment with these haiku.rag functions (use them directly, no imports needed): ## Available Functions ### search(query, limit=10) -> list[dict] Search the knowledge base using hybrid search (vector + full-text). Returns list of dicts with keys: chunk_id, content, document_id, document_title, document_uri, score, page_numbers, headings ### list_documents(limit=10, offset=0) -> list[dict] List available documents in the knowledge base. Returns list of dicts with keys: id, title, uri, created_at ### get_document(id_or_title) -> str | None Get the full text content of a document by ID, title, or URI. Returns the document content as a string, or None if not found. ### get_docling_document(id_or_title) -> DoclingDocument | None Get the structured DoclingDocument object for advanced analysis. Returns a DoclingDocument object, or None if not found. See "DoclingDocument API" section below for how to use it. ### ask(question) -> str Ask a question using the QA agent with RAG. Returns the answer as a string. Use this for semantic analysis that benefits from LLM reasoning. ## Standard Library Modules You can import: json, re, collections, math, statistics, itertools, functools, datetime, typing ## Strategy Guide 1. **Explore First**: Start by listing documents or searching to understand what's available. Document names may differ from filenames (e.g., "tbmed593.pdf" might be stored as "TB MED 593" or similar). 2. **If get_document returns None**: Use `list_documents()` to see actual document titles, or `search()` to find relevant content. 3. **Iterative Refinement**: Run code, examine results, adjust your approach based on what you find. 4. **Use print() Liberally**: The REPL captures stdout - print intermediate results to see what you're working with. 5. **Aggregate with Code**: For counting, averaging, or comparing across documents, write loops and use collections. 6. **Use ask() for Semantic Analysis**: When you need to understand meaning or interpret content, use the ask() function. 7. **Cite Your Sources**: Track which documents/chunks informed your answer for citation. ## DoclingDocument API When you call `get_docling_document(id_or_title)`, you get a DoclingDocument object for structured document analysis. ### Properties - `doc.texts` - List of all text items (paragraphs, headings, etc.) - `doc.tables` - List of all tables - `doc.pictures` - List of all pictures/figures - `doc.name` - Document name ### Methods - `doc.iterate_items(with_groups=False)` - Iterate all items with hierarchy level Returns tuples of (item, level) where level is nesting depth - `doc.export_to_markdown()` - Export entire document as markdown string ### Text Item Properties - `item.text` - The text content - `item.label` - Type: TITLE, PARAGRAPH, SECTION_HEADER, LIST_ITEM, etc. - `item.prov` - Provenance (page numbers, bounding boxes) ### Table Access - `table.data.num_rows`, `table.data.num_cols` - Dimensions - `table.data.table_cells` - List of TableCell objects - `cell.text`, `cell.start_row_offset_idx`, `cell.start_col_offset_idx` ### Example Usage ```python doc = get_docling_document("My Document") # Get all headings headings = [t.text for t in doc.texts if "HEADER" in str(t.label)] # Iterate with structure for item, level in doc.iterate_items(): print(" " * level + item.text[:50]) # Extract table data for table in doc.tables: for cell in table.data.table_cells: print(f"Row {cell.start_row_offset_idx}, Col {cell.start_col_offset_idx}: {cell.text}") ``` ## Example Patterns ### Counting documents matching a condition ```python docs = list_documents(limit=100) count = 0 for doc in docs: content = get_document(doc['id']) if content and 'keyword' in content.lower(): count += 1 print(f"Found in: {doc['title']}") print(f"Total: {count}") ``` ### Aggregating data across documents ```python import re numbers = [] results = search("financial data", limit=20) for r in results: matches = re.findall(r'\$([\d,]+)', r['content']) for m in matches: numbers.append(int(m.replace(',', ''))) print(f"Average: ${sum(numbers)/len(numbers):,.2f}") ``` ### Using ask() for semantic analysis ```python # First search to find relevant content results = search("machine learning approaches") # Then use ask() to synthesize an answer summary = ask("What are the main machine learning approaches discussed?") print(summary) ``` ## Workflow 1. **ALWAYS start by using execute_code** to explore the knowledge base 2. Run multiple code blocks as needed to gather information 3. After collecting data, provide your final answer ## Output Format After executing code and gathering information, provide: 1. A clear answer to the user's question 2. Key findings from your analysis 3. References to specific documents/chunks that informed your answer CRITICAL: You MUST call execute_code at least once before providing your answer. Never give up without trying to execute code first. role: system - content: What is the total revenue across all quarterly reports? role: user - content: |- We need revenue from quarterly reports. Search for "quarterly report" and revenue. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"quarterly report revenue\", limit=50)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''], r[''page_numbers''])\n"}' name: execute_code id: call_8cd1wnf6 type: function - content: '{"code":"results = search(\"quarterly report revenue\", limit=50)\nprint(len(results))\nfor r in results[:5]:\n print(r[''document_title''], r[''score''], r[''page_numbers''])\n","stdout":"3\nQ1 Report 0.03226645663380623 []\nQ2 Report 0.03226645663380623 []\nQ3 Report 0.032258063554763794 []\n","stderr":"","success":true}' role: tool tool_call_id: call_8cd1wnf6 - content: |- We have 3 reports: Q1, Q2, Q3. Likely Q4 also exists. Search again for Q4. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"Q4 Report\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n"}' name: execute_code id: call_mgo4t2ty type: function - content: '{"code":"results = search(\"Q4 Report\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n","stdout":"3\nQ1 Report\nQ2 Report\nQ3 Report\n","stderr":"","success":true}' role: tool tool_call_id: call_mgo4t2ty - content: |- All quarterly reports 1-3 only? Maybe Q4 is in separate doc. Search “Quarterly Report 4”. role: assistant tool_calls: - function: arguments: '{"code":"results = search(\"Quarterly Report 4\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n"}' name: execute_code id: call_3d3jutqn type: function - content: '{"code":"results = search(\"Quarterly Report 4\", limit=10)\nprint(len(results))\nfor r in results:\n print(r[''document_title''])\n","stdout":"3\nQ1 Report\nQ2 Report\nQ3 Report\n","stderr":"","success":true}' role: tool tool_call_id: call_3d3jutqn - content: |2- It appears only Q1‑Q3 reports are present in the index. We need revenue figures from each. We'll retrieve the full text of each report and extract numbers labeled “Revenue”. role: assistant tool_calls: - function: arguments: '{"code":"docs = [''Q1 Report'', ''Q2 Report'', ''Q3 Report'']\nrevenues = {}\nimport re\nfor d in docs:\n content = get_document(d)\n if content:\n # Find revenue lines\n matches = re.findall(r''Revenue.*?:\\s*\\$([\\d,\\.]+)'', content, re.IGNORECASE)\n if matches:\n # take first match\n rev = float(matches[0].replace('','',''''))\n revenues[d] = rev\n else:\n revenues[d] = None\n else:\n revenues[d] = None\nprint(revenues)\n"}' name: execute_code id: call_2rg8jz4m type: function - content: '{"code":"docs = [''Q1 Report'', ''Q2 Report'', ''Q3 Report'']\nrevenues = {}\nimport re\nfor d in docs:\n content = get_document(d)\n if content:\n # Find revenue lines\n matches = re.findall(r''Revenue.*?:\\s*\\$([\\d,\\.]+)'', content, re.IGNORECASE)\n if matches:\n # take first match\n rev = float(matches[0].replace('','',''''))\n revenues[d] = rev\n else:\n revenues[d] = None\n else:\n revenues[d] = None\nprint(revenues)\n","stdout":"{''Q1 Report'': None, ''Q2 Report'': None, ''Q3 Report'': None}\n","stderr":"","success":true}' role: tool tool_call_id: call_2rg8jz4m - content: |- No revenue found by pattern. Let's inspect content snippet. role: assistant tool_calls: - function: arguments: '{"code":"content = get_document(''Q1 Report'')\nprint(content[:500])\n"}' name: execute_code id: call_oqz8cbe0 type: function - content: '{"code":"content = get_document(''Q1 Report'')\nprint(content[:500])\n","stdout":"Sales report Q1: Revenue was $100,000.\n","stderr":"","success":true}' role: tool tool_call_id: call_oqz8cbe0 - content: |- Need to handle different phrasing. Search for "$" pattern. role: assistant tool_calls: - function: arguments: '{"code":"import re\nrevs={}\nfor d in [''Q1 Report'',''Q2 Report'',''Q3 Report'']:\n content=get_document(d)\n if content:\n vals=re.findall(r''\\$([\\d,]+)'',content)\n if vals:\n rev=sum(int(v.replace('','','''')) for v in vals)\n else:\n rev=None\n else:\n rev=None\n revs[d]=rev\nprint(revs)\n"}' name: execute_code id: call_2j8yqv8s type: function - content: '{"code":"import re\nrevs={}\nfor d in [''Q1 Report'',''Q2 Report'',''Q3 Report'']:\n content=get_document(d)\n if content:\n vals=re.findall(r''\\$([\\d,]+)'',content)\n if vals:\n rev=sum(int(v.replace('','','''')) for v in vals)\n else:\n rev=None\n else:\n rev=None\n revs[d]=rev\nprint(revs)\n","stdout":"{''Q1 Report'': 100000, ''Q2 Report'': 150000, ''Q3 Report'': 200000}\n","stderr":"","success":true}' role: tool tool_call_id: call_2j8yqv8s - content: "**Answer**\n\nThe total revenue reported across the three quarterly reports is:\n\n\\- Q1 Report: **$100,000** \ \n\\- Q2 Report: **$150,000** \n\\- Q3 Report: **$200,000**\n\n**Total Revenue (all quarters combined): $450,000**\n\n**Key Findings & Sources**\n\n1. **Q1 Report** – revenue extraction from the text \"Revenue was $100,000.\"\n - Source snippet: *“Sales report Q1: Revenue was $100,000.”*\n2. **Q2 Report** – revenue extracted from \"$150,000\" in the document.\n3. **Q3 Report** – revenue extracted from \"$200,000\" in the document.\n\nAll figures were obtained by searching each document for dollar amounts and summing them. No Q4 report was found in the available documents." role: assistant - content: |- 1 validation error: ```json [ { "type": "json_invalid", "loc": [], "msg": "Invalid JSON: expected value at line 1 column 1", "input": "**Answer**\n\nThe total revenue reported across the three quarterly reports is:\n\n\\- Q1 Report: **$100,000** \n\\- Q2 Report: **$150,000** \n\\- Q3 Report: **$200,000**\n\n**Total Revenue (all quarters combined): $450,000**\n\n**Key Findings & Sources**\n\n1. **Q1 Report** – revenue extraction from the text \"Revenue was $100,000.\"\n - Source snippet: *“Sales report Q1: Revenue was $100,000.”*\n2. **Q2 Report** – revenue extracted from \"$150,000\" in the document.\n3. **Q3 Report** – revenue extracted from \"$200,000\" in the document.\n\nAll figures were obtained by searching each document for dollar amounts and summing them. No Q4 report was found in the available documents." } ] ``` Fix the errors and try again. role: user model: gpt-oss reasoning_effort: low stream: false tool_choice: auto tools: - function: description: |- Execute Python code in the sandboxed environment. The code has access to haiku.rag functions (search, list_documents, get_document, get_docling_document, ask) and safe standard library modules (json, re, collections, math, statistics, itertools, functools, datetime, typing). Use print() to output results. Variables persist between executions. Structured result with success status, stdout, and stderr. name: execute_code parameters: additionalProperties: false properties: code: description: Python code to execute. type: string required: - code type: object strict: true type: function - function: description: Result from RLM agent execution. name: final_result parameters: $defs: CodeExecution: additionalProperties: false description: Result of executing a code block in the RLM sandbox. properties: code: description: The Python code that was executed type: string stderr: description: Standard error captured during execution type: string stdout: description: Standard output captured during execution type: string success: description: Whether execution completed without error type: boolean required: - code - stdout - stderr - success type: object additionalProperties: false properties: answer: description: The answer to the user's question type: string code_executions: description: History of code executions during the RLM session items: $ref: '#/$defs/CodeExecution' type: array required: - answer type: object type: function uri: http://localhost:11434/v1/chat/completions response: headers: content-length: - '1126' content-type: - application/json parsed_body: choices: - finish_reason: tool_calls index: 0 message: content: '' reasoning: Need to output JSON. role: assistant tool_calls: - function: arguments: '{"answer":"The total revenue reported across the three quarterly reports is:\n- Q1 Report: $100,000\n- Q2 Report: $150,000\n- Q3 Report: $200,000\n\n**Total Revenue (all quarters combined): $450,000**\n\n**Key Findings \u0026 Sources**\n1. Q1 Report – revenue extracted from the text \"Revenue was $100,000.\" (Source: Sales report Q1 text)\n2. Q2 Report – revenue extracted from \"$150,000\" in the document.\n3. Q3 Report – revenue extracted from \"$200,000\" in the document.\n\nAll figures were obtained by searching each document for dollar amounts and summing them. No Q4 report was found in the available documents.","code_executions":[]}' name: final_result id: call_1ouq42ea index: 0 type: function created: 1769703378 id: chatcmpl-830 model: gpt-oss object: chat.completion system_fingerprint: fp_ollama usage: completion_tokens: 195 prompt_tokens: 3387 total_tokens: 3582 status: code: 200 message: OK version: 1