Skip to content

feat(blocks): add agent block type#336

Merged
saltenasl merged 6 commits intomainfrom
ls/add-agentic-block-type
Mar 9, 2026
Merged

feat(blocks): add agent block type#336
saltenasl merged 6 commits intomainfrom
ls/add-agentic-block-type

Conversation

@saltenasl
Copy link
Contributor

@saltenasl saltenasl commented Mar 9, 2026

Agent blocks store an AI prompt that converts to Python comments for compatibility when exported to Jupyter, Quarto, Percent, and Marimo formats. Roundtrip conversion preserves the block type and content via deepnote_source metadata.

Summary by CodeRabbit

  • New Features

    • Added Agent blocks as a new executable block type; prompts render as commented Python content, roundtrip across notebook formats, and expose execution-related fields and concise labels (first non-empty line, truncated).
  • Tests

    • Added tests for Python rendering, labeling, roundtrip conversion, execution-field behavior, and executable-type detection.
  • Chores

    • Bumped package versions for related modules.

Agent blocks store an AI prompt that converts to Python comments
for compatibility when exported to Jupyter, Quarto, Percent, and
Marimo formats. Roundtrip conversion preserves the block type and
content via deepnote_source metadata.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 9, 2026

📝 Walkthrough

Walkthrough

Adds a new "agent" block type: schema and exported AgentBlock type, Python code generation that renders agent prompts as commented Python blocks, type guard and helper to detect agent blocks, and labels for agent blocks. Registers 'agent' as an executable and code block type across runtime, conversion, reactivity, and MCP tooling. Adds roundtrip conversion handling and tests (unit and integration) for agent behavior. Bumps package versions where relevant.

Sequence Diagram(s)

sequenceDiagram
    participant DeepnoteFile as DeepnoteFile
    participant PythonCodeGen as PythonCodeGen
    participant Converter as Converter
    participant RoundtripTool as RoundtripTool
    participant ExecutionEngine as ExecutionEngine
    participant ASTAnalyzer as ASTAnalyzer

    DeepnoteFile->>PythonCodeGen: createPythonCode(block)
    PythonCodeGen->>PythonCodeGen: isAgentBlock? / createPythonCodeForAgentBlock
    PythonCodeGen-->>Converter: emit code cell with commented prompt
    Converter->>RoundtripTool: convert to target format
    RoundtripTool->>Converter: parse back, preserve metadata
    Converter-->>DeepnoteFile: restore AgentBlock with metadata
    DeepnoteFile->>ExecutionEngine: register executable block type 'agent'
    DeepnoteFile->>ASTAnalyzer: include 'agent' in supported cell types
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Updates Docs ⚠️ Warning Pull request introduces new agent block type implementation but fails to update documentation in packages/blocks/README.md. Add agent block documentation to packages/blocks/README.md under Supported Block Types section and update internal roadmap.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title accurately describes the primary change: adding a new 'agent' block type across the codebase with supporting schema, utilities, and exports.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Mar 9, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.47%. Comparing base (74f9b27) to head (3c11dbc).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #336      +/-   ##
==========================================
+ Coverage   83.42%   83.47%   +0.04%     
==========================================
  Files         122      123       +1     
  Lines        7355     7375      +20     
  Branches     2040     2046       +6     
==========================================
+ Hits         6136     6156      +20     
  Misses       1219     1219              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/reactivity/src/ast-analyzer.ts (1)

16-33: 🧹 Nitpick | 🔵 Trivial

Consider removing 'agent' from AST_ANALYZER_SUPPORTED_CELL_TYPES_LIST.

Agent blocks generate only Python comments—# [agent block] followed by prompt lines. The AST analyzer extracts variable definitions and uses, which comments never contain. Including agent blocks here adds processing overhead without yielding any dependency data.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/reactivity/src/ast-analyzer.ts` around lines 16 - 33,
AST_ANALYZER_SUPPORTED_CELL_TYPES_LIST includes 'agent' even though agent blocks
only produce comments and cannot yield variable definitions; remove the 'agent'
entry from the AST_ANALYZER_SUPPORTED_CELL_TYPES_LIST tuple in ast-analyzer.ts
and verify any code that references this list (e.g., functions that iterate over
AST_ANALYZER_SUPPORTED_CELL_TYPES_LIST) still behaves correctly—adjust callers
if they special-case 'agent' or rely on its presence and run relevant tests to
ensure no regressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/blocks/src/deepnote-file/deepnote-file-schema.ts`:
- Line 396: You added agentBlockSchema to the deepnote schema but did not update
the Deepnote skill docs and generated schema; regenerate the Deepnote skill
schema and add documentation: run the generator command `pnpm --filter
`@deepnote/cli` generate:skill-schema` to regenerate
skills/deepnote/references/schema.ts, then create or update the appropriate
skills/deepnote/references/blocks-*.md file to document the new agentBlockSchema
block (include its fields, usage, and examples) so the .deepnote format and
block docs remain in sync.

In `@packages/mcp/src/tools/writing.ts`:
- Around line 413-417: Replace the inline executable-type check that sets the
candidate variable with a call to the shared helper: import and use
isExecutableBlockType from `@deepnote/blocks/executable-blocks.ts` to evaluate
spec.type (i.e., candidate = isExecutableBlockType(spec.type)); if 'button' and
'big-number' are not covered by isExecutableBlockType keep those special cases
by OR-ing them (e.g., candidate = isExecutableBlockType(spec.type) || spec.type
=== 'button' || spec.type === 'big-number'), and remove the hardcoded array and
startsWith logic to avoid drift.

---

Outside diff comments:
In `@packages/reactivity/src/ast-analyzer.ts`:
- Around line 16-33: AST_ANALYZER_SUPPORTED_CELL_TYPES_LIST includes 'agent'
even though agent blocks only produce comments and cannot yield variable
definitions; remove the 'agent' entry from the
AST_ANALYZER_SUPPORTED_CELL_TYPES_LIST tuple in ast-analyzer.ts and verify any
code that references this list (e.g., functions that iterate over
AST_ANALYZER_SUPPORTED_CELL_TYPES_LIST) still behaves correctly—adjust callers
if they special-case 'agent' or rely on its presence and run relevant tests to
ensure no regressions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 53e7fb12-bd61-4875-a552-cf31ef9f7235

📥 Commits

Reviewing files that changed from the base of the PR and between b5b4b4c and a51c248.

📒 Files selected for processing (11)
  • packages/blocks/src/blocks/agent-blocks.ts
  • packages/blocks/src/blocks/executable-blocks.ts
  • packages/blocks/src/deepnote-file/deepnote-file-schema.ts
  • packages/blocks/src/python-code.test.ts
  • packages/blocks/src/python-code.ts
  • packages/cli/src/utils/block-label.ts
  • packages/convert/src/roundtrip-all-formats.test.ts
  • packages/convert/src/utils.ts
  • packages/mcp/src/tools/writing.ts
  • packages/reactivity/src/ast-analyzer.ts
  • packages/runtime-core/src/execution-engine.ts

coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 9, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/blocks/src/blocks/executable-blocks.test.ts`:
- Around line 6-35: The test silently allows invalid block types because the
arrays (executableTypes and nonExecutableTypes) are plain strings and the inline
cast on block uses as DeepnoteBlock; change the arrays to be typed with "as
const satisfies readonly DeepnoteBlock['type'][]" so TypeScript will catch typos
(e.g., replace 'divider' with the correct 'separator'), and stop using a broad
"as DeepnoteBlock" on the constructed block—use the strongly-typed array element
to build the block or cast a narrower type to ensure isExecutableBlock and
DeepnoteBlock types are validated at compile time.

In `@packages/cli/src/utils/block-label.test.ts`:
- Around line 116-201: Add a new test case to the agent blocks suite that
verifies getBlockLabel correctly handles prompts with special characters: create
a DeepnoteBlock with content containing quotes, backticks, and Unicode (e.g.,
`He said "hello" — 🧪 \`code\``), then assert getBlockLabel returns the first
non-empty line with those characters preserved and truncated behavior still
applies (if you provide a long special-character string, assert length is 50 and
endsWith('…')). Locate tests near other agent cases and add it alongside
existing getBlockLabel usages.

In `@packages/convert/package.json`:
- Line 3: Update the package.json "version" field from "3.2.1" to "3.3.0" to
reflect the new feature (agent block support); locate the "version" key in the
package.json for the convert package and change its value to 3.3.0, then run
your usual release/packaging checks (e.g., npm/yarn version or CI) to ensure
consistency.

In `@packages/mcp/src/tools/writing.test.ts`:
- Around line 69-87: Replace the plain property-existence checks in the test
with Jest's more idiomatic assertions: when asserting on the created Deepnote
notebook block (variable block retrieved after loadDeepnoteFile), use
expect(block).toHaveProperty('executionCount') and
expect(block).toHaveProperty('outputs') instead of expect('executionCount' in
block).toBe(true) and expect('outputs' in block).toBe(true); keep the rest of
the test (handleWritingTool call and checks for block.type and block.content)
unchanged.

In `@packages/reactivity/src/ast-analyzer.test.ts`:
- Around line 77-91: Replace the benign agent block content in the test for
getBlockDependencies with a code-like, parseable payload (e.g., containing
variable assignments, function defs or import statements) that would produce
dependencies if it were analyzed as code; keep the block type 'agent' and the
existing expectation that only the code block (id '1') defines variable 'a' so
the agent is ignored. Update the mockBlocks variable in ast-analyzer.test.ts
(the agent block with id '2') to use the parseable content and leave the
expect(result).toEqual assertion unchanged to ensure regressions where agent
content is incorrectly parsed are caught.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1ef0c728-bae9-43e5-bcbe-fdd0d055e5a7

📥 Commits

Reviewing files that changed from the base of the PR and between a51c248 and 034a2c7.

📒 Files selected for processing (10)
  • packages/blocks/package.json
  • packages/blocks/src/blocks/executable-blocks.test.ts
  • packages/cli/package.json
  • packages/cli/src/utils/block-label.test.ts
  • packages/convert/package.json
  • packages/mcp/package.json
  • packages/mcp/src/tools/writing.test.ts
  • packages/reactivity/package.json
  • packages/reactivity/src/ast-analyzer.test.ts
  • packages/runtime-core/package.json

@saltenasl saltenasl marked this pull request as ready for review March 9, 2026 13:34
@saltenasl saltenasl requested a review from a team as a code owner March 9, 2026 13:34
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
packages/cli/src/utils/block-label.test.ts (1)

116-201: ⚠️ Potential issue | 🟡 Minor

Add one agent-label case with special characters.

This suite still doesn't pin quotes, backticks, or Unicode on the first non-empty line, so label extraction can regress without tripping a test.

Suggested addition
   it('truncates long prompts', () => {
     const block: DeepnoteBlock = {
       id: 'test-id',
       type: 'agent',
       content: 'This is a very long agent prompt that should be truncated because it exceeds fifty characters',
       metadata: {},
       sortingKey: 'a',
       blockGroup: 'group',
     }
     const label = getBlockLabel(block)
     expect(label.length).toBe(50)
     expect(label.endsWith('…')).toBe(true)
   })
+
+  it('preserves special characters in the first non-empty line', () => {
+    const block: DeepnoteBlock = {
+      id: 'test-id',
+      type: 'agent',
+      content: '\nHe said "hello" — 🧪 `code`',
+      metadata: {},
+      sortingKey: 'a',
+      blockGroup: 'group',
+    }
+    expect(getBlockLabel(block)).toBe('prompt: He said "hello" — 🧪 `code`')
+  })

As per coding guidelines, "Test edge cases, error handling, and special characters in test files".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/utils/block-label.test.ts` around lines 116 - 201, Add a
test case to the agent blocks suite to cover special characters: create a
DeepnoteBlock with type 'agent' whose content's first non-empty line includes
quotes, backticks, and Unicode (e.g., `“Quote” 'single' `backtick` π`) and
assert getBlockLabel(block) returns "prompt: " plus that exact first non-empty
line (respecting trimming and truncation rules); this ensures getBlockLabel
correctly extracts and preserves special characters—update
packages/cli/src/utils/block-label.test.ts near the other agent tests and
reference getBlockLabel in the assertion.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/blocks/src/python-code.test.ts`:
- Around line 24-98: Add a new exact-output test in the "Agent blocks" describe
for createPythonCode that supplies an agent block whose content contains special
characters (quotes, backticks, and Unicode, and e.g. embedded # or triple
quotes) to ensure the comment renderer doesn't alter formatting; call
createPythonCode with that block and assert the result equals the exact expected
string (including leading "# [agent block] System prompt:\n" and per-line "# "
prefixes or the "(empty system prompt)" form as appropriate) so the test fails
if quoting/backtick/Unicode handling changes.

---

Duplicate comments:
In `@packages/cli/src/utils/block-label.test.ts`:
- Around line 116-201: Add a test case to the agent blocks suite to cover
special characters: create a DeepnoteBlock with type 'agent' whose content's
first non-empty line includes quotes, backticks, and Unicode (e.g., `“Quote”
'single' `backtick` π`) and assert getBlockLabel(block) returns "prompt: " plus
that exact first non-empty line (respecting trimming and truncation rules); this
ensures getBlockLabel correctly extracts and preserves special characters—update
packages/cli/src/utils/block-label.test.ts near the other agent tests and
reference getBlockLabel in the assertion.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 16f194eb-9e96-4d70-9965-9f88ada674bd

📥 Commits

Reviewing files that changed from the base of the PR and between 034a2c7 and 697b115.

📒 Files selected for processing (4)
  • packages/blocks/src/blocks/agent-blocks.ts
  • packages/blocks/src/python-code.test.ts
  • packages/cli/src/utils/block-label.test.ts
  • packages/cli/src/utils/block-label.ts

@saltenasl saltenasl requested a review from tkislan March 9, 2026 13:50
@saltenasl saltenasl enabled auto-merge (squash) March 9, 2026 14:20
@saltenasl saltenasl merged commit 5ca1fcc into main Mar 9, 2026
21 checks passed
@saltenasl saltenasl deleted the ls/add-agentic-block-type branch March 9, 2026 14:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants