{"id":"batch_run","name":"Batch Run","alias":"BatchRun","aliases":[],"description_short":"Run any other tool over many records, from a list, a SQL query, a table or an uploaded CSV, and collect the results in a file or a table.","description_long":"Run one tool over many records at once.\n\n    This is the only way to fan a tool out: every other tool takes exactly one item.\n\n    Sources: `rows` (records in the call itself), `sql` (a BigQuery query),\n    `table` (a whole catalog table), `file` (a CSV/TSV uploaded at\n    https://app.botify.com/:organization/:project/o/storage/tmp, or the output of\n    a previous batch).\n\n    Small sources run immediately and return their results. Larger ones run as a\n    background job: you get a job_id to poll with batch_status, and the records\n    never enter this conversation.\n\n    The output is a temporary JSONL file whose URL is directly usable as the\n    `file` source of a next batch, which is how several tools are chained. Each\n    line is {row, item, response, error} -- the original row and mapped item are\n    both kept, so results stay attributable and source columns survive chaining.\n\n    Use tool_documentation on the target tool first: item_map has to match its\n    item schema. Use dry_run to check a mapping against real records before\n    paying for the whole source.\n    ","description_tool_prompt":"Run another tool over many records (a list, a SQL query, a table or an uploaded CSV) and write the results to a file or a table. Read the target tool's schema with tool_documentation before writing item_map, and use dry_run to validate it on a few records first.","source":null,"conversation_examples":[],"tags":[],"available_in_chat":false,"available_in_deepthink":false,"available_in_mcp":true,"mcp_audience":"all","config":{"type":"object","properties":{"on_error":{"$ref":"#/$defs/OnError","default":"skip","description":"skip: record the failure and carry on. fail_job: stop the whole batch on the first failing record."},"chunk_size":{"default":50,"description":"Records sent to the tool at once.","maximum":500,"minimum":1,"title":"Chunk Size","type":"integer"},"inline_max_rows":{"default":10,"description":"Above this many records, the batch runs as a job.","maximum":100,"minimum":1,"title":"Inline Max Rows","type":"integer"}},"required":[],"$defs":{"OnError":{"enum":["skip","fail_job"],"type":"string"}}},"item":{"type":"object","properties":{"tool":{"description":"Id of the tool to run over every record. Use tool_documentation to read its item schema before writing item_map.","title":"Tool","type":"string"},"source":{"$ref":"#/$defs/SourceSpec","description":"Where the records come from."},"item_map":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"Projection from a source record onto the tool's item, using {{row.<column>}} (ex: {\"url\": \"{{row.page_url}}\"}). Omit it when the records already have the tool's item shape.","title":"Item Map"},"sink":{"anyOf":[{"$ref":"#/$defs/SinkSpec"},{"type":"null"}],"default":null,"description":"Where results go. Defaults to a temporary gzipped JSONL file whose URL can be passed straight back as a file source."},"tool_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"The target tool's own config, shared by every record.","title":"Tool Config"},"dry_run":{"default":false,"description":"Run only the first 5 records and return them in full, launching nothing. Use it to check a mapping or a prompt against a large source in one turn.","title":"Dry Run","type":"boolean"}},"required":["tool","source"],"$defs":{"FileFormat":{"enum":["auto","jsonl","csv","tsv"],"type":"string"},"FileSink":{"description":"A temporary JSONL file in project storage, readable back as a source.","properties":{"type":{"const":"file","default":"file","title":"Type","type":"string"},"gzip":{"default":true,"description":"Compress the output.","title":"Gzip","type":"boolean"}},"title":"FileSink","type":"object"},"FileSource":{"description":"Rows from an uploaded CSV/TSV, or from a previous batch's JSONL output.","properties":{"type":{"const":"file","default":"file","title":"Type","type":"string"},"url":{"description":"File URL. Upload a local file at https://app.botify.com/:organization/:project/o/storage/tmp and pass the returned URL, or reuse the sink URL of a previous batch. Public HTTP(S) URLs are accepted too. CSV, TSV and JSONL, gzip allowed.","title":"Url","type":"string"},"format":{"$ref":"#/$defs/FileFormat","default":"auto","description":"File format, or auto-detect."}},"required":["url"],"title":"FileSource","type":"object"},"RowsSource":{"description":"Records passed directly in the call.","properties":{"type":{"const":"rows","default":"rows","title":"Type","type":"string"},"rows":{"description":"The records to process, one object per call.","items":{"additionalProperties":true,"type":"object"},"minItems":1,"title":"Rows","type":"array"}},"required":["rows"],"title":"RowsSource","type":"object"},"SinkSpec":{"discriminator":{"mapping":{"file":"#/$defs/FileSink","table":"#/$defs/TableSink"},"propertyName":"type"},"oneOf":[{"$ref":"#/$defs/FileSink"},{"$ref":"#/$defs/TableSink"}]},"SourceSpec":{"discriminator":{"mapping":{"file":"#/$defs/FileSource","rows":"#/$defs/RowsSource","sql":"#/$defs/SqlSource","table":"#/$defs/TableSource"},"propertyName":"type"},"oneOf":[{"$ref":"#/$defs/RowsSource"},{"$ref":"#/$defs/SqlSource"},{"$ref":"#/$defs/TableSource"},{"$ref":"#/$defs/FileSource"}]},"SqlSource":{"description":"Rows from a BigQuery query over the project's catalog.","properties":{"type":{"const":"sql","default":"sql","title":"Type","type":"string"},"query":{"description":"BigQuery Standard SQL over catalog tables. Prefix every table with \"catalog.\" (ex: catalog.crawl_pages_20251201). Same access as tables_query.","title":"Query","type":"string"},"limit":{"anyOf":[{"minimum":1,"type":"integer"},{"type":"null"}],"default":null,"description":"Stop after this many rows.","title":"Limit"}},"required":["query"],"title":"SqlSource","type":"object"},"TableSink":{"description":"A table in the project's editable catalog.","properties":{"type":{"const":"table","default":"table","title":"Type","type":"string"},"table":{"description":"Destination table in the catalog.","pattern":"^[A-Za-z_][A-Za-z0-9_]{0,1023}$","title":"Table","type":"string"},"row_map":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"Column projection, using {{item.<field>}}, {{response.<field>}}, {{error}} and {{row.<column>}}. Defaults to `row`, `item`, `response` and `error` columns.","title":"Row Map"},"replace_existing":{"default":false,"description":"Replace the table instead of appending to it.","title":"Replace Existing","type":"boolean"}},"required":["table"],"title":"TableSink","type":"object"},"TableSource":{"description":"Every row of one catalog table.","properties":{"type":{"const":"table","default":"table","title":"Type","type":"string"},"table":{"description":"Table name, with or without the \"catalog.\" prefix.","pattern":"^(?:catalog\\.)?[A-Za-z_][A-Za-z0-9_]*$","title":"Table","type":"string"},"limit":{"anyOf":[{"minimum":1,"type":"integer"},{"type":"null"}],"default":null,"description":"Stop after this many rows.","title":"Limit"}},"required":["table"],"title":"TableSource","type":"object"}}},"response":{"$defs":{"SinkPointer":{"description":"Where a batch's output landed.","properties":{"type":{"enum":["file","table"],"title":"Type","type":"string"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Sink file URL, reusable as the source of a next batch.","title":"Url"},"table":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Destination table.","title":"Table"},"rows_written":{"default":0,"description":"Records written.","title":"Rows Written","type":"integer"}},"required":["type"],"title":"SinkPointer","type":"object"}},"description":"What a batch returns, whichever path it took.","properties":{"mode":{"description":"dry_run and inline carry their results; job carries a job_id to poll with batch_status.","enum":["dry_run","inline","job"],"title":"Mode","type":"string"},"tool":{"description":"The tool that was run.","title":"Tool","type":"string"},"results":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"default":null,"description":"One {item, response, error} object per record.","title":"Results"},"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Poll it with batch_status.","title":"Job Id"},"execution_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Underlying Cloud Run execution.","title":"Execution Id"},"rows_total":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Records the batch will process.","title":"Rows Total"},"rows_ok":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Records that succeeded.","title":"Rows Ok"},"rows_error":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Records that failed.","title":"Rows Error"},"estimated_credits":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Credits the batch is expected to cost.","title":"Estimated Credits"},"sink":{"anyOf":[{"$ref":"#/$defs/SinkPointer"},{"type":"null"}],"default":null,"description":"Where the output landed."},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"One line about the outcome.","title":"Message"}},"required":["mode","tool"],"title":"BatchRunResult","type":"object"},"has_canvas":false,"open_canvas_automatically":false}