<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="feed/pretty-atom-feed.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  
  <title>DJ Adams</title>
  <subtitle>Reserving the right to be wrong</subtitle>
  <link href="https://qmacro.org/feed.xml" rel="self" />
  <link href="https://qmacro.org/blog/" />
  <updated>2026-10-07T00:00:00Z</updated>
  <id>https://qmacro.org/blog/</id>
  <author>
    <name>DJ Adams</name>
  </author>
  <entry>
    <title>Markdown previews in lf with leaf</title>
    <link href="https://qmacro.org/blog/posts/2026/10/07/markdown-previews-in-lf-with-leaf/" />
    <updated>2026-10-07T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/10/07/markdown-previews-in-lf-with-leaf/</id>
    <content type="html">&lt;p&gt;Today I&#39;m finding I&#39;m working Markdown even more, and the delta is mostly in
read-mode, rather than write-mode. Reading agent and skill files, intent
summaries, product requirement documents and more, especially in the context
of &lt;a href=&quot;https://qmacro.org/tags/joule-studio/&quot;&gt;Joule Studio&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I use the terminal file manager &lt;a href=&quot;https://github.com/gokcehan/lf&quot;&gt;lf&lt;/a&gt; which is
very configurable. The configuration mechanisms include a &lt;code&gt;previewer&lt;/code&gt; file
which is a shell script that calls different tools to preview different file
types. Until just now, mine looked like this:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/bin/sh&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;basename&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;
Dockerfile &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; *.dockerfile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; highlight &lt;span class=&quot;token parameter variable&quot;&gt;-O&lt;/span&gt; ansi &lt;span class=&quot;token parameter variable&quot;&gt;--syntax&lt;/span&gt; Dockerfile &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
*.jpeg &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; *.jpg &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; *.png&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; exiftool &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
*.json&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; jq &lt;span class=&quot;token parameter variable&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
*&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; batcat &lt;span class=&quot;token parameter variable&quot;&gt;--style&lt;/span&gt; plain &lt;span class=&quot;token parameter variable&quot;&gt;--color&lt;/span&gt; always &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;esac&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, I use specific tools for a small number of content types, and fall back
to the default of &lt;a href=&quot;https://github.com/sharkdp/bat&quot;&gt;bat&lt;/a&gt; for everything else.&lt;/p&gt;
&lt;p&gt;Separately from the &lt;code&gt;lf&lt;/code&gt; context I&#39;ve been using
&lt;a href=&quot;https://github.com/charmbracelet/glow&quot;&gt;glow&lt;/a&gt; to render Markdown in the
terminal. It does a lovely job. But running it in the context of another tool
like &lt;code&gt;lf&lt;/code&gt; &lt;a href=&quot;https://github.com/gokcehan/lf/issues/2011&quot;&gt;is a struggle&lt;/a&gt; due to it
not sending ANSI codes.&lt;/p&gt;
&lt;p&gt;Luckily, I just found &lt;a href=&quot;https://leaf.rivolink.mg/&quot;&gt;leaf&lt;/a&gt;, another terminal based
Markdown viewer. And with the &lt;a href=&quot;https://leaf.rivolink.mg/docs/features/inline-rendering/&quot;&gt;inline
rendering&lt;/a&gt; option I
can force it to emit ANSI.&lt;/p&gt;
&lt;p&gt;So now I&#39;ve added another line to my &lt;code&gt;case ... esac&lt;/code&gt; construct above:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;*.md &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; *.markdown&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; leaf &lt;span class=&quot;token parameter variable&quot;&gt;--inline&lt;/span&gt; ansi &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and I can now comfortably read Markdown content, rendered beautifully:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://qmacro.org/images/2026/10/markdown-rendering-with-leaf.png&quot; alt=&quot;Markdown rendering with leaf&quot;&gt;&lt;/p&gt;
&lt;p&gt;(Yes, that screenshot is deliberately meta).&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Exploring Joule Studio skills</title>
    <link href="https://qmacro.org/blog/posts/2026/10/05/exploring-joule-studio-skills/" />
    <updated>2026-10-05T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/10/05/exploring-joule-studio-skills/</id>
    <content type="html">&lt;p&gt;The new &lt;a href=&quot;https://help.sap.com/docs/joule-studio/joule-studio/joule-studio-for-cli-pro-code-development-in-joule-studio&quot;&gt;Joule Studio
CLI&lt;/a&gt;
recently landed, in the form of &lt;code&gt;jl&lt;/code&gt;. This is what we use on the command line
to initialise a new Joule Studio project. What does that mean? Well, amongst
other things, it means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you work on your project using a coding agent harness such as Claude Code or
OpenCode&lt;/li&gt;
&lt;li&gt;such agent harnesses know about, and how to make use of
&lt;a href=&quot;https://agentskills.io/specification&quot;&gt;skills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;for Joule Studio powered development, there is a curated set of skills
specifically designed for building enterprise agents and more&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Initialising a new project not only creates some harness-specific
configuration&lt;a href=&quot;https://qmacro.org/blog/posts/2026/10/05/exploring-joule-studio-skills/#footnotes&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; but also retrieves this set of skills.&lt;/p&gt;
&lt;h2 id=&quot;skills-retrieved&quot;&gt;Skills retrieved&lt;/h2&gt;
&lt;p&gt;Here&#39;s what that looks like:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# /tmp&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; jl init opencode myproj &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; myproj

Fetching system skills&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
  ✓ agent &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+37 resources&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  ✓ agent-evaluation &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+8 resources&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  ✓ agent-extension &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+9 resources&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  ✓ data-product &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+11 resources&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  ✓ deploy-solution
  ✓ intent-analysis
  ✓ joule-studio-cli
  ✓ mcp-mock-config &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+4 resources&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  ✓ mcp-translation-file
  ✓ n8n-workflow &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+21 resources&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  ✓ product-requirements-document &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+1 resource&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  ✓ setup-solution &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+2 resources&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  ✓ specification &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+1 resource&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
✓ &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt; skills initialized &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; myproj/.agents/skills.

Creating configuration files:
  ✓ myproj/opencode.json — created

OpenCode MCP config initialized: /tmp/myproj
&lt;span class=&quot;token comment&quot;&gt;# /tmp/myproj&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;The specific skills retrieved here will depend on various circumstances,
you may see a slightly different list.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;browsing-the-skills&quot;&gt;Browsing the skills&lt;/h2&gt;
&lt;p&gt;I wanted to explore these skills and get a better understanding of what they
were. So I wrote a quick shell script (yes, I wrote it, not AI, to help
maintain my cognitive fitness&lt;a href=&quot;https://qmacro.org/blog/posts/2026/10/05/exploring-joule-studio-skills/#footnotes&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;), which allows me to
browse them and get an overview.&lt;/p&gt;
&lt;h3 id=&quot;skills-overview&quot;&gt;Skills overview&lt;/h3&gt;
&lt;p&gt;The default is to render the skill content like this, in a pager:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://qmacro.org/images/2026/10/skillbrowser-glow.gif&quot; alt=&quot;Skill browser in action&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;skills-detail&quot;&gt;Skills detail&lt;/h3&gt;
&lt;p&gt;If more details are sought, then setting the env var &lt;code&gt;SB_DETAIL&lt;/code&gt; will cause
the selected skill to be opened in a file browser, to allow viewing and browsing
of any related resources, like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://qmacro.org/images/2026/10/skillbrowser-detail.gif&quot; alt=&quot;Skill browser (detail) in action&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-brief-look-at-the-script&quot;&gt;A brief look at the script&lt;/h2&gt;
&lt;p&gt;The shell script,
&lt;a href=&quot;https://github.com/qmacro/dotfiles/blob/main/scripts/sb&quot;&gt;sb&lt;/a&gt;, now forms part
of my personal development environment (&lt;a href=&quot;https://qmacro.org/tags/pde/&quot;&gt;PDE&lt;/a&gt;) and also uses other
tools that I have in there. Here&#39;s the script in its entirety:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-eo&lt;/span&gt; pipefail
&lt;span class=&quot;token builtin class-name&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;FILEBROWSER&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;lf

&lt;span class=&quot;token function-name function&quot;&gt;fm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/^---$/ { if (n++) exit; next } n&#39;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function-name function&quot;&gt;pv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token builtin class-name&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;skillfile&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt;
  &lt;span class=&quot;token builtin class-name&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$2&lt;/span&gt;

  fm &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$skillfile&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; yq &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&quot;&#92;(.name|ascii_upcase) (&#92;(.metadata.version))&#92;n&#92;n&#92;(.description)&quot;&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fmt&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-w&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$width&lt;/span&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;pv&lt;/span&gt; fm

&lt;span class=&quot;token function-name function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token builtin class-name&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;loc&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${1&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;.}&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token builtin class-name&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;descwidth&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$((&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;$&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tput cols&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token builtin class-name&quot;&gt;local&lt;/span&gt; selection

  &lt;span class=&quot;token assign-left variable&quot;&gt;selection&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;$(
    while read -r skill; do
      echo &quot;&lt;span class=&quot;token variable&quot;&gt;$skill&lt;/span&gt;&quot; &#92;
        | awk -F/ &#39;{print &lt;span class=&quot;token variable&quot;&gt;$4&lt;/span&gt;, &lt;span class=&quot;token variable&quot;&gt;$0&lt;/span&gt;}&#39;
    done &amp;lt;&amp;lt;&amp;lt; &quot;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$loc&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;SKILL.md&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; fzf &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
        --with-nth&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
        &lt;span class=&quot;token parameter variable&quot;&gt;--preview&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;pv {2} &lt;span class=&quot;token variable&quot;&gt;$descwidth&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cut&lt;/span&gt; -d&lt;span class=&quot;token string&quot;&gt;&#39; &#39;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;

  if test -z &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$SB_DETAIL&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;; then
    glow -p &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$selection&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  else
    &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$FILEBROWSER&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dirname&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$selection&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;
  fi

}

main &quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$@&lt;/span&gt;&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The general idea is that &lt;code&gt;SKILL.md&lt;/code&gt; files are found, passed to
&lt;a href=&quot;https://github.com/junegunn/fzf&quot;&gt;fzf&lt;/a&gt; for selection and
preview&lt;a href=&quot;https://qmacro.org/blog/posts/2026/10/05/exploring-joule-studio-skills/#footnotes&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;, and then a selected skill can be drilled
into as well.&lt;/p&gt;
&lt;p&gt;Here are some notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;fm&lt;/code&gt; function extracts &lt;a href=&quot;https://docs.github.com/en/contributing/writing-for-github-docs/using-yaml-frontmatter&quot;&gt;YAML
frontmatter&lt;/a&gt;
which is expected to be found between two &lt;code&gt;---&lt;/code&gt; lines.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;pv&lt;/code&gt; function takes a skill file (fully qualified path and name) and also
a width, uses &lt;code&gt;fm&lt;/code&gt; to extract the frontmatter from it, and then uses &lt;code&gt;yq&lt;/code&gt; to
extract various values from the frontmatter, emitting them nicely, and
line-wrapped to a certain width with the &lt;code&gt;fmt&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;Like this:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;SETUP-SOLUTION (1.0.0)

Set up the solution structure with a
solution.yaml and assets folder, each
containing an asset with an asset.yaml
file. Used to create a solution, to create
an asset and to set up a multi-asset
solution.&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;These two script-local functions are exported to be available to any
subprocesses, useful for when &lt;code&gt;fzf&lt;/code&gt; spawns a shell to run the command
specified in the &lt;code&gt;--preview&lt;/code&gt; option.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;main&lt;/code&gt; function will default to the current directory (&lt;code&gt;.&lt;/code&gt;) if no
location is specified to search for skills in.&lt;/p&gt;
&lt;p&gt;It then:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Calculates a width that is slightly less than half the current terminal
width, to send to the &lt;code&gt;fm&lt;/code&gt; function so that the skill info fits into
&lt;code&gt;fzf&lt;/code&gt;&#39;s default preview window shape.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Uses &lt;code&gt;find&lt;/code&gt; to search for the full paths of any &lt;code&gt;SKILL.md&lt;/code&gt; files, which
look like this: &lt;code&gt;./.agents/skills/setup-solution/SKILL.md&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Processes these full paths with &lt;code&gt;awk&lt;/code&gt; to emit the significant part
(&lt;code&gt;setup-solution&lt;/code&gt; in this example) to be used in &lt;code&gt;fzf&lt;/code&gt;&#39;s selection list,
and also the entire path, to be used for subsequent processing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The resulting output is then passed to &lt;code&gt;fzf&lt;/code&gt; to present a simple selection
and preview UI, as shown in the video.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If a selection is made, &lt;code&gt;cut&lt;/code&gt; is then used to select the second value that
is emitted from &lt;code&gt;fzf&lt;/code&gt; (the full path to the selected skill file).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Finally, either (if the &lt;code&gt;SB_DETAIL&lt;/code&gt; env var is set) the the configured file
browser&lt;a href=&quot;https://qmacro.org/blog/posts/2026/10/05/exploring-joule-studio-skills/#footnotes&quot;&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt; is invoked on the directory, or the Markdown
rendered &lt;code&gt;glow&lt;/code&gt; is used to render the actual &lt;code&gt;SKILL.md&lt;/code&gt; content in paging
mode for easy reading.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&#39;s pretty much it. The script may change a little over time, but it works
for me now, and removes the friction I had which was stopping me from exploring
the detail of these important assets.&lt;/p&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;At the time of writing, this configuration consists of a section defining an
MCP server and how to invoke it. More on that another time, perhaps.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Also, as shell scripts (particularly Bash shell scripts, my favourite) are
what agents use to get their work done in many cases, it&#39;s always good to
stay on top of things to really understand what they&#39;re doing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I&#39;m &lt;a href=&quot;https://www.google.com/search?q=site%3Aqmacro.org+fzf&quot;&gt;a big fan&lt;/a&gt; of
&lt;code&gt;fzf&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I use &lt;a href=&quot;https://github.com/gokcehan/lf&quot;&gt;lf&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</content>
  </entry>
  <entry>
    <title>A community graph for people and things - onedevatlas</title>
    <link href="https://qmacro.org/blog/posts/2026/10/01/a-community-graph-for-people-and-things-onedevatlas/" />
    <updated>2026-10-01T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/10/01/a-community-graph-for-people-and-things-onedevatlas/</id>
    <content type="html">&lt;p&gt;Mike Zaschka, speaker, developer and active member of the community, has &lt;a href=&quot;https://www.linkedin.com/posts/mike-zaschka-7395949_sap-abap-ui5-ugcPost-7510710834222948352-xfEr/&quot;&gt;just
announced&lt;/a&gt;
&amp;quot;onedevatlas&amp;quot;, which feels to me like something we need but didn&#39;t realise it.&lt;/p&gt;
&lt;p&gt;The SAP community has produced various catalogues of tools and libraries in the
past, and these have been great. But perhaps in today&#39;s age, where it&#39;s easier
than ever to create new software, the need for awareness and knowledge of the
tools and libraries that are being built, and of the people building them, is
greater than ever. Moreover, the way such interlinked data can be maintained
and consumed is perhaps also coalescing in parallel with how graphs of
information are now core components of agentic computing. &lt;a href=&quot;https://qmacro.org/tags/rdf&quot;&gt;RDF&lt;/a&gt;
anyone?&lt;/p&gt;
&lt;p&gt;I am minded to think about the difference between previous catalogues, and
today&#39;s ambitions with onedevatlas, as being similar to how it was between
&lt;a href=&quot;https://en.wikipedia.org/wiki/Yahoo_Directory&quot;&gt;Yahoo!&lt;/a&gt; - a predominantly
human-maintained catalogue of resources on the Web - and Google - which
subsequently came along with a sledgehammer of a search engine that did away
with the need for explicitly curated structure.&lt;/p&gt;
&lt;p&gt;Seeing how Mike navigates between nodes and across arcs (yes, I did choose
those words specifically) in his demo video, gives us a glimpse at what&#39;s
promised. I for one am intrigued.&lt;/p&gt;
&lt;p&gt;Mike&#39;s asking for feedback, so what are you waiting for?&lt;/p&gt;
&lt;h2 id=&quot;postscript&quot;&gt;Postscript&lt;/h2&gt;
&lt;p&gt;Mike &lt;a href=&quot;https://www.linkedin.com/posts/mike-zaschka-7395949_little-did-i-know-how-ridiculously-fun-it-share-7511401407821053953-z7pU/&quot;&gt;followed
up&lt;/a&gt;
with some thoughts on what vehicle might be cool to use to explore the space.
Mike&#39;s original demo video reminded me of
&lt;a href=&quot;https://en.wikipedia.org/wiki/Elite_(video_game)&quot;&gt;Elite&lt;/a&gt;, the classic space
trading video game first published for the BBC Micro (I had one) in 1984, with
this spaceship:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://qmacro.org/images/2026/10/elite-spaceship.png&quot; alt=&quot;Elite spaceship&quot;&gt;&lt;/p&gt;
&lt;p&gt;I&#39;d choose that :-)&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>CAP September 2026 release</title>
    <link href="https://qmacro.org/blog/posts/2026/09/24/cap-september-2026-release/" />
    <updated>2026-09-24T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/09/24/cap-september-2026-release/</id>
    <content type="html">&lt;p&gt;The &lt;a href=&quot;https://cap.cloud.sap/docs/releases/2026/sep26&quot;&gt;September 2026 release of
CAP&lt;/a&gt; is out. This is the first
minor release following the major release upgrade in June of this year, and
brings CAP Node.js to 10.1 and CAP Java to 5.1.&lt;/p&gt;
&lt;p&gt;It&#39;s &amp;quot;only&amp;quot; a minor release, but goodness me there&#39;s a lot of great stuff. Let
me take you through some of the highlights, which are split into different
categories.&lt;/p&gt;
&lt;h2 id=&quot;cap-native-ai&quot;&gt;CAP Native AI&lt;/h2&gt;
&lt;p&gt;First there&#39;s the CAP Native AI category, which has come about mostly because
there&#39;s been so much work in this area. After all, CAP is the foundation for
much of our AI business solutions and central to our &lt;a href=&quot;https://architecture.learning.sap.com/docs/ai-native-north-star-architecture/platform-layer&quot;&gt;AI North Star
architecture&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://qmacro.org/images/2026/09/ai-north-star-architecture-platform-layer-cap.png&quot; alt=&quot;The &amp;quot;Platform Layer&amp;quot; section of the AI North Star Architecture document showing
that the AI Golden Path is built upon CAP&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;a-new-guide&quot;&gt;A new guide&lt;/h3&gt;
&lt;p&gt;It&#39;s been almost a full-time job keeping track of all the progress, and keeping
our corresponding research and learning in line with what&#39;s being developed.
Luckily there&#39;s an early incarnation of a new top-level guide called &lt;a href=&quot;https://cap.cloud.sap/docs/guides/ai/&quot;&gt;Native
AI&lt;/a&gt;, which covers all the important
topics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Vector embeddings: natively supported by HANA, an essential mechanism for
AI-powered searching, matching and recommendations (particularly useful in
UIs).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MCP: a fundamental building block of today&#39;s agentic era, enabling agents to
embellish their context and actually effect things in the wider world. The
MCP adapter plugin is now GA, by the way!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A2A: like MCP, agent support in CAP is a mere annotation away, plus optional
Markdown based skills and guardrails in this case. What&#39;s more, in addition
to the &lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/11/local-first-dev-with-cap-node-js/&quot;&gt;mocking&lt;/a&gt;
we&#39;re familiar with, we get a mocked LLM with the &lt;a href=&quot;https://github.com/cap-js/agents&quot;&gt;agents
plugin&lt;/a&gt; plus a super useful UI for
interaction. All out of the box, following CAP&#39;s classic developer-first
approach. The agents plugin is in Gamma status right now.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;You may wish to check out our current Hands-on SAP Dev live stream series on
&lt;a href=&quot;https://www.youtube.com/playlist?list=PLTKB1hyt4LXs&quot;&gt;CAP in the age of AI&lt;/a&gt;
which covers these topics and more.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There&#39;s even a section of this new guide that&#39;s all about &lt;a href=&quot;https://cap.cloud.sap/docs/guides/ai/joule-integration&quot;&gt;integration with
Joule&lt;/a&gt;; in the spirit
of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Release_early,_release_often&quot;&gt;release early, release
often&lt;/a&gt; philosophy
popularised by the one and only Eric S. Raymond in his essay &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Cathedral_and_the_Bazaar&quot;&gt;The Cathedral and
the Bazaar&lt;/a&gt;, it&#39;s a
very early and raw release, just hinting at the structure and content to come.&lt;/p&gt;
&lt;h3 id=&quot;a-scenario-to-try-out-all-the-ai-concepts&quot;&gt;A scenario to try out all the AI concepts&lt;/h3&gt;
&lt;p&gt;Going back to talk of agents, it&#39;s sometimes hard to conjure up a
realistic-enough scenario to kick the tyres with, but CAP has you covered too
with the &lt;a href=&quot;https://cap.cloud.sap/docs/guides/ai/xtravels-sample&quot;&gt;XTravels Sample for
AI&lt;/a&gt;; it&#39;s not too simple
as to be underwhelming, but not overly dry and boring either. It allows us to
explore lots of different concepts and protocols, such as subagency,
delegation, A2A and MCP, as well as the more classic ideas of reuse, data APIs
and more.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://qmacro.org/images/2026/09/cap-ai.gif&quot; alt=&quot;CAP/AI gif&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;much-love-for-vector-embeddings&quot;&gt;Much love for vector embeddings&lt;/h3&gt;
&lt;p&gt;While some features might come to CAP Node.js first, and then to CAP Java, or
vice versa, things are generally eventually consistent. CAP-native support for
vector embeddings is one such feature, already supported for CAP Java but now
also for CAP Node.js.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://cap.cloud.sap/docs/guides/ai/embeddings&quot;&gt;Vector Embeddings&lt;/a&gt; guide
has also had an overhaul, which is where we can find the details of how to get
embeddings working locally with SQLite which doesn&#39;t have native support for
them. In a classic &amp;quot;&lt;a href=&quot;https://qmacro.org/blog/posts/2026/07/24/timeless-principles-agnostic-design-and-the-power-of-caps-abstractions/#:~:text=one%20of%20CAP%27s%20%22-,magic%20made%20simple,-%22%20moments%2C%20and%20is&quot;&gt;magic made
simple&lt;/a&gt;&amp;quot;
way, the CAP team have done a serious amount of heavy lifting and configuration
for us to emulate what&#39;s required. Kudos to the team.&lt;/p&gt;
&lt;h3 id=&quot;keeping-our-ai-overlords-happy&quot;&gt;Keeping our AI overlords happy&lt;/h3&gt;
&lt;p&gt;In my not so humble opinion, the CAP documentation, affectionately and
unofficially known as &amp;quot;Capire&amp;quot;, stands out as a great example of what we should
all be striving for with respect to sharing knowledge, know-how and best
practices.&lt;/p&gt;
&lt;p&gt;The audience for this knowledge is not just limited to us humans, far from it.
One way that we make great strides forward in agentic computing is to make sure
our agents know what to do, and how to do it ... in the best possible way.&lt;/p&gt;
&lt;p&gt;Agent skills are useful, for sure, but in the same way that we have stop-gap
measures to cover the last mile between the scope of any given language model
pre-training and the reality today, skills cover the delta between what we
consider now as best practice, and what was the previous status quo in that
regard.&lt;/p&gt;
&lt;p&gt;To that end, it&#39;s more important than ever that documentation remains
accurate and concise, and tells us - humans and LLMs alike - what to do and how
to do it best, and in a way that is readable (and token-friendly too).&lt;/p&gt;
&lt;p&gt;And so &lt;a href=&quot;https://cap.cloud.sap/docs/releases/2026/sep26#capire-4-ai-evolution&quot;&gt;the team has made machine-friendly &lt;em&gt;representations&lt;/em&gt; of the &lt;em&gt;resource&lt;/em&gt;
that is
Capire&lt;/a&gt;,
with the content and a sitemap in what is the lingua franca between humans and
their &lt;a href=&quot;https://www.youtube.com/watch?v=8lcUHQYhPTE&quot;&gt;AI overlords&lt;/a&gt; - Markdown.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://qmacro.org/images/2026/09/insect-overlords.png&quot; alt=&quot;Still image from the classic &amp;quot;I for one welcome our insect overlords&amp;quot; scene
from The Simpsons&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For more on resources &amp;amp; representations, see &lt;a href=&quot;https://qmacro.org/blog/posts/2003/02/28/conneg-and-the-duality-of-weblogs/&quot;&gt;&#39;Conneg&#39; and the duality of
weblogs&lt;/a&gt; and also
&lt;a href=&quot;https://qmacro.org/blog/posts/2009/08/20/coffeeshop-screencast-http-conneg-resource-representations-and-json/&quot;&gt;Coffeeshop screencast: HTTP conneg, resource representations and
JSON&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;the-cds-language-family&quot;&gt;The CDS language family&lt;/h2&gt;
&lt;p&gt;The next category within which we find updates in the September 2026 release is the CDS language family. Briefly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Boolean expressions are now wrapped in a &lt;code&gt;CASE WHEN&lt;/code&gt; construct for HANA SQL,
as bare predicates aren&#39;t permitted in the list of elements for selection.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It&#39;s now possible to extend views that already have a conditional clause; the
new condition is combined with &lt;code&gt;AND&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When using nested inline projections, we can now use the &lt;code&gt;key&lt;/code&gt; keyword;
typically this is needed when the key elements need to be extended to inside
the projection to provide the uniqueness required.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are minor but really nice improvements to the life of a domain expert
or modeller, allowing us more flexibility and power as we continue to
&lt;a href=&quot;https://qmacro.org/blog/posts/2026/02/09/shift-left-with-cap/&quot;&gt;shift left&lt;/a&gt;, avoid bloat and
moving parts, and - above all - fight the lazy agentic pattern of verbose and
unnecessary generation of almost-immediate technical debt.&lt;/p&gt;
&lt;h2 id=&quot;cap-runtimes&quot;&gt;CAP Runtimes&lt;/h2&gt;
&lt;p&gt;Following the same category pattern as in the release notes, we now come to the
runtimes category, for Node.js and Java.&lt;/p&gt;
&lt;p&gt;In fact, before we &lt;a href=&quot;https://en.wiktionary.org/wiki/bifurcate&quot;&gt;bifurcate&lt;/a&gt;,
there&#39;s a feature in this minor release that applies to both runtimes, relating
to fuzzy search, a fault-tolerant search feature of SAP HANA Cloud. Results are
now sorted by match score, unless that order is overridden by an &lt;code&gt;$orderby&lt;/code&gt;
parameter in the query.&lt;/p&gt;
&lt;h3 id=&quot;node-js&quot;&gt;Node.js&lt;/h3&gt;
&lt;p&gt;Beyond the pretty amazing new feature that provides support for vector embeddings with SQLite in a Node.js context, there&#39;s also a further move towards an ever more lighter weight of dependencies. This is especially relevant in today&#39;s world of software supply chain attacks, and an ever smaller surface area is always desirable.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For more on this, see &lt;a href=&quot;https://www.youtube.com/watch?v=mRs3oQPOcgM&quot;&gt;Daniel Hutzel&#39;s keynote at reCAP this
year&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://qmacro.org/images/2026/09/shai-hulud.png&quot; alt=&quot;A still image from the keynote recording, showing the giant desert
sandworms from Frank Herbert&#39;s Dune universe, known as Shai Hulud, which is
also the name given to a recent and notorious software supply chain malware
worm&quot;&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To this end, and powered by the Node-native Fetch API that was embraced in the
CAP Node.js runtime earlier this year, and which has allowed the team to shed a
whole load of dependencies already, the reliance on the SAP Cloud SDK is also
further reduced, down to a subset of destination types.&lt;/p&gt;
&lt;p&gt;Basically, there are some authentication types such as &lt;code&gt;OnPremise&lt;/code&gt; that are not
supported yet - but for all the others, the Fetch-API plus CAP Node.js is all
we need.&lt;/p&gt;
&lt;h3 id=&quot;java&quot;&gt;Java&lt;/h3&gt;
&lt;p&gt;There are quite a few updates for the Java runtime, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Support for the OData v4.01 JSON batch request format; v4.01 is the latest
version in the OData family of standards and the move from &lt;code&gt;multipart/mixed&lt;/code&gt;
is welcome, as far as I&#39;m concerned :-)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To learn more about OData, you might want to take a look at the &lt;a href=&quot;https://developers.sap.com/tutorials/mission-odata-deep-dive&quot;&gt;OData
Deep Dive&lt;/a&gt;
mission.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When building a query, we can use the &lt;code&gt;excluding()&lt;/code&gt; method to avoid having to
specify a long list of the elements wanted, instead specifying a short list
of the elements that are &lt;em&gt;not&lt;/em&gt; wanted.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When building for hierarchy views (such as in Fiori Tree Tables) the
&lt;code&gt;@cds.default.order&lt;/code&gt; annotation can be used to specify the desired sort order
of siblings.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The CDS Maven plugin used for CDS-related build steps has undergone some
optimisations, for faster builds, a fast mode for the &lt;code&gt;watch&lt;/code&gt; goal, and
static implementation generation for faster reflection-free access.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tools&quot;&gt;Tools&lt;/h2&gt;
&lt;p&gt;Did someone say tools and the CLI? I&#39;m here for that. First, shell completion,
which has been around for a while, but has had a complete overhaul in this
September 2026 release. The upshot is that it&#39;s much faster, more responsive
and puts less stress on your shell as it works. Pretty awesome. Shell
completion is available for Bash, Zsh, fish ... and even PowerShell!&lt;/p&gt;
&lt;p&gt;Completions are available for the commands, options and then (where relevant)
files and directories - completion for these is via standard shell mechanisms,
which is great.&lt;/p&gt;
&lt;p&gt;And it&#39;s nice to see IntelliJ getting lots of love - version 3 of the CDS
plugin for that IDE now supports CDS 10, and has some nice new formatting
options too.&lt;/p&gt;
&lt;h2 id=&quot;plugins&quot;&gt;Plugins&lt;/h2&gt;
&lt;p&gt;We&#39;re almost done, but we can&#39;t forget all the work that goes into the CAP
plugins, can we? While they&#39;re not part of the core (the clue&#39;s in the name,
right?) they can be essential components in our projects, and many of them are
maintained by the CAP team themselves.&lt;/p&gt;
&lt;p&gt;Here&#39;s a &lt;a href=&quot;https://cap.cloud.sap/docs/releases/2026/sep26#cap-plugins&quot;&gt;list of plugins that have had updates in this
release&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The ORD plugin - which is now also open source 🎉 - now supports generating
Open Resource Discovery definitions for lots of protocols, including OData
and MCP.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Attachments plugin now supports single attachments, instead of the
standard list construct. There are also some major release properties that
you need to pay attention to, in both runtimes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Notifications plugin for the Node.js runtime has been overhauled, and for
Java there&#39;s an initial Alpha release too.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Last but not least, there&#39;s a new n8n&lt;a href=&quot;https://qmacro.org/blog/posts/2026/09/24/cap-september-2026-release/#footnotes&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; plugin, also
in Alpha, for both runtimes. This plugin lets us trigger n8n workflows
directly from CAP.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;For a minor release, that&#39;s pretty spectacular, I&#39;d say. You can check out all
the &lt;a href=&quot;https://cap.cloud.sap/docs/releases/2026/sep26&quot;&gt;release notes&lt;/a&gt;, which
themselves have links to further reading, in the usual place, and it&#39;s also
worth keeping an eye on the &lt;a href=&quot;https://cap.cloud.sap/docs/releases/2026/changelog&quot;&gt;2026
Changelog&lt;/a&gt; too.&lt;/p&gt;
&lt;p&gt;Happy learning!&lt;/p&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;The name &amp;quot;n8n&amp;quot; is a meta-contraction of &amp;quot;node[auto]mation&amp;quot;.&lt;/li&gt;
&lt;/ol&gt;
</content>
  </entry>
  <entry>
    <title>Making OAuth 2.0 auth code flows work between containers and their host OS</title>
    <link href="https://qmacro.org/blog/posts/2026/09/22/making-oauth-2-0-auth-code-flows-work-between-containers-and-their-host-os/" />
    <updated>2026-09-22T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/09/22/making-oauth-2-0-auth-code-flows-work-between-containers-and-their-host-os/</id>
    <content type="html">&lt;p&gt;The example here relates to using the &lt;code&gt;jl&lt;/code&gt; CLI, the &lt;a href=&quot;https://help.sap.com/docs/joule-studio/joule-studio/cli-reference&quot;&gt;command line tool for
Joule
Studio&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unless otherwise stated, activities described here all happen in the container.&lt;/p&gt;
&lt;h2 id=&quot;starting-the-authentication-flow&quot;&gt;Starting the authentication flow&lt;/h2&gt;
&lt;p&gt;To use &lt;code&gt;jl&lt;/code&gt; in a project, we need to first
&lt;a href=&quot;https://help.sap.com/docs/joule-studio/joule-studio/cli-reference?locale=en-US#authentication&quot;&gt;authenticate&lt;/a&gt;
with a Joule Studio backend, using &lt;code&gt;jl login&lt;/code&gt;, specifying the sign-in URL
obtained from our Joule Studio &amp;quot;Develop &amp;gt; Authorizations&amp;quot; settings:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://qmacro.org/images/2026/09/joule-studio-develop-authorizations.png&quot; alt=&quot;The Develop &amp;gt; Authorization settings in Joule
Studio&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here&#39;s what it looks like when &lt;code&gt;jl login &amp;lt;url&amp;gt;&lt;/code&gt; is invoked (details elided
for obvious security reasons, and lines split for readability):&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;; jl login &quot;https://api.eu12.studio.joule.cloud.sap/cli/v1?appTid=bafe9663-...
&amp;issuerUrl=https%3A%2F%2Fagy....accounts400.ondemand.com
&amp;clientId=ad445849-...&quot;

Opening browser to log in to https://agy....accounts400.ondemand.com ...
If the browser does not open, copy the URL below and open it manually.

  https://agy....accounts400.ondemand.com/oauth2/authorize
  ?response_type=code
  &amp;client_id=ad445849-...
  &amp;redirect_uri=http%3A%2F%2F127.0.0.1%3A43963%2Fcallback
  &amp;code_challenge=tW6537dp_...
  &amp;code_challenge_method=S256
  &amp;state=uJW...
  &amp;scope=openid+offline_access
  &amp;app_tid=bafe9663-...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is the start of a three-legged OAuth 2.0 login flow.&lt;/p&gt;
&lt;h2 id=&quot;visiting-the-url&quot;&gt;Visiting the URL&lt;/h2&gt;
&lt;p&gt;Assuming that there&#39;s no browser in the container to invoke, we&#39;ll need to
explicitly select the URL and visit it manually, using a browser at the host OS
level (macOS in my case).&lt;/p&gt;
&lt;p&gt;If we look closely at the URL we&#39;ll see it includes a &lt;code&gt;redirect_uri&lt;/code&gt; parameter
which indicates the URL that we are to be redirected to once authentication in
the browser has happened.&lt;/p&gt;
&lt;p&gt;Here&#39;s that &lt;code&gt;redirect_uri&lt;/code&gt; parameter and value from the URL above:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;redirect_uri=http%3A%2F%2F127.0.0.1%3A43963%2Fcallback&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and here&#39;s what it looks like without URL encoding:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;redirect_uri=http://127.0.0.1:43963/callback&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This particular value (specifically the port number) will be used in
examples that follow.&lt;/p&gt;
&lt;h2 id=&quot;how-the-flow-works&quot;&gt;How the flow works&lt;/h2&gt;
&lt;p&gt;The idea is that the &lt;code&gt;jl login&lt;/code&gt; process spawns a temporary HTTP server
which starts listening on that specific socket (i.e. &lt;code&gt;localhost&lt;/code&gt;, or
&lt;code&gt;127.0.0.1&lt;/code&gt;, plus the random port &lt;code&gt;43963&lt;/code&gt;), expecting a callback
to a URL that thus starts &lt;code&gt;http://127.0.0.1:43963/callback&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That callback comes via the browser, in that once the actual authentication
process has been completed successfully in the browser (at the authorization
server, &lt;code&gt;api.eu12.studio.joule.cloud.sap&lt;/code&gt;), the HTTP response is a redirect,
sending the browser to the &lt;code&gt;redirect_uri&lt;/code&gt; (&lt;code&gt;http://127.0.0.1:43963/callback&lt;/code&gt;)
with various parameters - that convey information from the authorization
server - added on to the end.&lt;/p&gt;
&lt;p&gt;This set of parameters includes one called &lt;code&gt;code&lt;/code&gt; which has the authorization
code that &lt;code&gt;jl&lt;/code&gt; needs.&lt;/p&gt;
&lt;p&gt;Here&#39;s an example of what such a complete callback URL looks like (again, with
some values elided, and lines split for readability):&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;http://127.0.0.1:43963/callback
  ?code=u7LpLuRfiutemU4GdWUbMH80E_...
  &amp;iss=https%3A%2F%2Fagy....accounts400.ondemand.com
  &amp;state=uJW...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once the browser accesses that callback URL, the code and the other parameter
values from the authorization server are effectively &amp;quot;received&amp;quot; by the temporary
HTTP server, which is part of &lt;code&gt;jl login&lt;/code&gt;, and are stored, completing the flow.&lt;/p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The problem&lt;/h2&gt;
&lt;p&gt;But the temporary HTTP server is running only in the container (where &lt;code&gt;jl login&lt;/code&gt; was called), and the random port is not published from the container out
to the container runtime&#39;s host.&lt;/p&gt;
&lt;p&gt;And as the browser operation is in the context of the host OS, the redirection
will fail (as there is nothing listening on &lt;code&gt;localhost&lt;/code&gt; at that random port at
the host OS level):&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://qmacro.org/images/2026/09/this-site-cant-be-reached.png&quot; alt=&quot;Browser error: &amp;quot;This site can&#39;t be
reached&amp;quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;and thus the whole authentication flow will not be completed.&lt;/p&gt;
&lt;h2 id=&quot;the-solution&quot;&gt;The solution&lt;/h2&gt;
&lt;p&gt;So we need to create a temporary tunnel from the host OS into the container, so
that the browser can reach that HTTP server in there.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We might think to influence the &lt;code&gt;jl login&lt;/code&gt; part by somehow supplying a fixed
PORT value which will be used instead of it picking a random one, a value
that we know about in advance and can have set up to have been published from
the container.&lt;/p&gt;
&lt;p&gt;Unfortunately:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;we need to do this before we even create the container&lt;/li&gt;
&lt;li&gt;there is no facility to specify this to &lt;code&gt;jl login&lt;/code&gt; anyway&lt;a href=&quot;https://qmacro.org/blog/posts/2026/09/22/making-oauth-2-0-auth-code-flows-work-between-containers-and-their-host-os/#footnotes&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;using-ssh-remote-port-forwarding&quot;&gt;Using SSH remote port forwarding&lt;/h3&gt;
&lt;p&gt;To create a tunnel, we can use
&lt;a href=&quot;https://man7.org/linux/man-pages/man1/ssh.1.html&quot;&gt;SSH&lt;/a&gt;&#39;s remote port
forwarding, with the &lt;code&gt;-R&lt;/code&gt; option.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;-L&lt;/code&gt; option creates a tunnel going from local&lt;a href=&quot;https://qmacro.org/blog/posts/2026/09/22/making-oauth-2-0-auth-code-flows-work-between-containers-and-their-host-os/#footnotes&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;
to remote, whereas the &lt;code&gt;-R&lt;/code&gt; option creates one from remote (the host OS) back
to local (the container), which is what we need in this case.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The port we need to specify on setting up the tunnel is the random port that
was assigned in the creation of the temporary HTTP server (&lt;code&gt;43963&lt;/code&gt; in this
example).&lt;/p&gt;
&lt;p&gt;But that port is quite hard to make out from that long URL.&lt;/p&gt;
&lt;h3 id=&quot;extracting-the-redirect-uri-port-from-the-url&quot;&gt;Extracting the redirect_uri port from the URL&lt;/h3&gt;
&lt;p&gt;So we can add some magic on to the end of the &lt;code&gt;jl login &amp;lt;url&amp;gt;&lt;/code&gt; command to use
&lt;code&gt;tee&lt;/code&gt; to capture the output to a file, and then use &lt;a href=&quot;https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Process-Substitution&quot;&gt;process
substitution&lt;/a&gt;
to process what contents would normally be written to that file, using more
shell commands, like this:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;jl login &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;url&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tee&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-Po&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;(?&amp;lt;=%3A)&#92;d{5}&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;grep&lt;/code&gt; command option &lt;code&gt;-P&lt;/code&gt; specifies we want to use Perl Compatible Regular
Expressions (PCRE) and &lt;code&gt;-o&lt;/code&gt; says that we just want the match, nothing else. The
&lt;code&gt;(?&amp;lt;=...)&lt;/code&gt; construct is a lookbehind assertion, the &lt;code&gt;&#92;d&lt;/code&gt; is a &amp;quot;digits&amp;quot;
character class, and the &lt;code&gt;{5}&lt;/code&gt; is a specific count of how many of that class
we&#39;re trying to match.&lt;/p&gt;
&lt;p&gt;In other words, &amp;quot;look for a string of 5 digits that are immediately preceded by
&lt;code&gt;%3A&lt;/code&gt; (the URL encoded version of the colon (&lt;code&gt;:&lt;/code&gt;)) and emit just those 5 digits&amp;quot;.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;jl login &lt;span class=&quot;token string&quot;&gt;&quot;https://api.eu12.studio.joule.cloud.sap/cli/v1?appTid=...&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;tee&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-Po&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;(?&amp;lt;=%3A)&#92;d{5}&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;emits not only the regular output, like this (long URL has been split
over multiple lines for readability):&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;Opening browser to log in to &lt;span class=&quot;token url&quot;&gt;https://agyx....accounts400.ondemand.com&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
If the browser does not open&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; copy the URL below and open it manually&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

  &lt;span class=&quot;token url&quot;&gt;https://agyx....accounts400.ondemand.com/oauth2/authorize&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;response_type&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;code
  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;client_id&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;redirect_uri&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;http&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3A&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2F&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2F127.0.0.1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3A43963&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;2Fcallback
  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;code_challenge&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;code_challenge_method&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;S256
  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;scope&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;openid&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;offline_access
  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;app_tid&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but also, thanks to the &lt;code&gt;| tee &amp;gt;( ... )&lt;/code&gt;, emits this:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;43963&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;creating-the-tunnel&quot;&gt;Creating the tunnel&lt;/h3&gt;
&lt;p&gt;At this point, we can open up a new shell session in the container (e.g. a new
pane in &lt;code&gt;tmux&lt;/code&gt;) and run:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;ssh&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;43963&lt;/span&gt;:localhost:43963 &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;username&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;@host.docker.internal&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;&amp;lt;username&amp;gt;&lt;/code&gt; is your host OS user (the username on macOS in my case).&lt;/p&gt;
&lt;h3 id=&quot;authenticating&quot;&gt;Authenticating&lt;/h3&gt;
&lt;p&gt;Once we&#39;ve successfully SSH&#39;d to the host OS, and have the host OS prompt, the
tunnel exists.&lt;/p&gt;
&lt;p&gt;We can now click the URL and the authentication flow will work correctly,
taking us first to the authentication server, then redirecting us successfully
via the tunnel back to the temporary HTTP server initiated by &lt;code&gt;jl login&lt;/code&gt;, and
the authentication information will be stored:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;✓ Logged in to &lt;span class=&quot;token url&quot;&gt;https://api.eu12.studio.joule.cloud.sap/cli/v1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;(&lt;/span&gt;session expires &lt;span class=&quot;token date number&quot;&gt;9/24/2026&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token time number&quot;&gt;1:18:14&lt;/span&gt; AM&lt;span class=&quot;token operator&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Success!&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;The different layers presented by containers and their host OSes, especially in
OAuth flow scenarios like this, can be tricky, but understanding what&#39;s
happening, and using standard tools to address the situation, turns out to be
quite straightforward.&lt;/p&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;I&#39;ve looked :-)&lt;/li&gt;
&lt;li&gt;Here, &amp;quot;local&amp;quot; refers to the container, i.e. where &lt;code&gt;ssh&lt;/code&gt; is invoked.&lt;/li&gt;
&lt;/ol&gt;
</content>
  </entry>
  <entry>
    <title>Notes on simple agentification of a CAP service</title>
    <link href="https://qmacro.org/blog/posts/2026/08/25/notes-on-simple-agentification-of-a-cap-service/" />
    <updated>2026-08-25T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/08/25/notes-on-simple-agentification-of-a-cap-service/</id>
    <content type="html">&lt;h2 id=&quot;baseline&quot;&gt;Baseline&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.npmjs.com/package/@cap-js/agents&quot;&gt;plugin for building agents based on the A2A
protocol&lt;/a&gt; is here.&lt;/p&gt;
&lt;p&gt;I start with the simple &lt;a href=&quot;https://github.com/capire/bookshop&quot;&gt;bookshop&lt;/a&gt; project
and add the plugin:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;gh repo clone capire/bookshop &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; bookshop &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; @cap-js/agents&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;agentification&quot;&gt;Agentification&lt;/h2&gt;
&lt;p&gt;I apply the &lt;code&gt;@agent&lt;/code&gt; annotation to the &lt;code&gt;CatalogService&lt;/code&gt; in &lt;code&gt;srv/cat-agent.cds&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-cds&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cds&quot;&gt;&lt;span class=&quot;token using keyword&quot;&gt;using&lt;/span&gt; { CatalogService } &lt;span class=&quot;token from keyword&quot;&gt;from&lt;/span&gt; &#39;./cat-&lt;span class=&quot;token keyword&quot;&gt;service&lt;/span&gt;&#39;;

annotate CatalogService with &lt;span class=&quot;token annotation important&quot;&gt;@agent;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;@agent&lt;/code&gt; annotation &lt;a href=&quot;https://github.com/capire/bookshop/commit/665650969f2d1c6e5ccc82aa2b3be3afe1158b67&quot;&gt;was added
recently&lt;/a&gt;
so this step is not needed now, except to illustrate how simple it is to add,
and where we might consider doing that, i.e. separately.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;startup-and-development-mode&quot;&gt;Startup and development mode&lt;/h2&gt;
&lt;p&gt;I start up a CAP server and ask for debug level output for the agents component:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;DEBUG&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;agents cds &lt;span class=&quot;token function&quot;&gt;watch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and observe the log output:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;agents&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; Adapter initialized &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; service&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;CatalogService&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; serving CatalogService &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;at:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/odata/v4/browse&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/rest/browse&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/hcql/browse&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/a2a/browse&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;decl:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;srv/cat-service.cds:3&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;impl:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;srv/cat-service.js&#39;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://localhost:4004/a2a/browse&quot;&gt;http://localhost:4004/a2a/browse&lt;/a&gt; is an A2A JSON-RPC endpoint that is
expecting POST requests&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://localhost:4004/a2a/browse/.well-known/agent-card.json&quot;&gt;http://localhost:4004/a2a/browse/.well-known/agent-card.json&lt;/a&gt; is the &lt;a href=&quot;https://agent2agent.info/docs/concepts/agentcard/&quot;&gt;agent
card&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://localhost:4004/a2a/browse/preview/&quot;&gt;http://localhost:4004/a2a/browse/preview/&lt;/a&gt; is a helper preview page that
provides a chat UI&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this default (development) mode, the plugin will mock an LLM, sending a
response like this to a chat message:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[Mock LLM] This is a mocked response from @cap-js/agents development mode. No real LLM was invoked.&lt;/p&gt;
&lt;p&gt;Tool result: count: 5
data[3]{createdAt,modifiedAt,ID,author,title,genre,stock,price,currency}:
&amp;quot;2026-08-25T12:44:18.880Z&amp;quot;,&amp;quot;2026-08-25T12:44:18.880Z&amp;quot;,201,Emily Brontë,Wuthering Heights,Drama,12,&amp;quot;11.11&amp;quot;,£
&amp;quot;2026-08-25T12:44:18.880Z&amp;quot;,&amp;quot;2026-08-25T12:44:18.880Z&amp;quot;,207,Charlotte Brontë,Jane Eyre,Drama,11,&amp;quot;12.34&amp;quot;,£
&amp;quot;2026-08-25T12:44:18.880Z&amp;quot;,&amp;quot;2026-08-25T12:44:18.880Z&amp;quot;,251,Edgar Allan Poe,The Raven -- 11% discount!,Mystery,333,&amp;quot;13.13&amp;quot;,$&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;connecting-to-a-real-llm&quot;&gt;Connecting to a real LLM&lt;/h2&gt;
&lt;p&gt;Connecting to an actual LLM is described on the plugin&#39;s
&lt;a href=&quot;https://github.com/cap-js/agents/blob/HEAD/.docs/connectivity.md&quot;&gt;Connectivity&lt;/a&gt;
page.&lt;/p&gt;
&lt;p&gt;I have access to an AI Core instance by means of a service key in a file
called &lt;code&gt;aicore.json&lt;/code&gt; in the project&#39;s parent directory. I also know that the
orchestration facilities that are needed are not in the default resource group,
for that instance, but in a resource group called &amp;quot;codejam-genai&amp;quot;.&lt;/p&gt;
&lt;h3 id=&quot;set-the-aicore-service-key-env-var&quot;&gt;Set the AICORE_SERVICE_KEY env var&lt;/h3&gt;
&lt;p&gt;Assigning the service key JSON data to the environment variable
&lt;code&gt;AICORE_SERVICE_KEY&lt;/code&gt; will allow the plugin to make the connection.&lt;/p&gt;
&lt;p&gt;I use &lt;code&gt;jq&lt;/code&gt;&#39;s &lt;code&gt;--compact-output&lt;/code&gt; (&lt;code&gt;-c&lt;/code&gt;) to remove whitespace and have the entire
JSON value as one string:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;AICORE_SERVICE_KEY&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;jq &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;/aicore.json&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;specify-the-llm-type-and-resource-group&quot;&gt;Specify the LLM type and resource group&lt;/h3&gt;
&lt;p&gt;I need to specify the resource group &amp;quot;codejam-genai&amp;quot;, and for that I can use
some plugin configuration, specifically &lt;code&gt;cds.requires.llm.resourceGroup&lt;/code&gt;. As
I&#39;m going to be specifying a child of the &lt;code&gt;llm&lt;/code&gt; node here, I should be
sure to explicitly specify the value for the &lt;code&gt;kind&lt;/code&gt; too (based on the way
configuration merging takes place). This makes sense anyway as resource groups
are somewhat AI Core specific.&lt;/p&gt;
&lt;p&gt;There&#39;s already a &lt;code&gt;.cdsrc.yaml&lt;/code&gt; file in the project with a &lt;code&gt;cds.requires.auth&lt;/code&gt;
node, so I add the configuration to the end, so it looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;cds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;requires&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;&quot;[production]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;auth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; mocked &lt;span class=&quot;token comment&quot;&gt;# as a sample app run with mocked auth also in production&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;llm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;aicore&#39;&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;resourceGroup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;codejam-genai&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;restart&quot;&gt;Restart&lt;/h2&gt;
&lt;p&gt;After restarting the CAP server (the &amp;quot;watch&amp;quot; mode ignores YAML file changes right now)
the response to the chat message is from a real LLM, and looks like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hello! How can I help you today? I can assist you with browsing books,
checking availability, or placing orders through the CatalogService. Feel
free to ask anything! 😊&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here&#39;s what is emitted in the CAP server log, too:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;agents&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; request &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;conversation:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;-&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;service:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;CatalogService&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;method:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;message/send&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;text:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;hi&#39;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;agents&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; Initializing LLM &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; model&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;anthropic--claude-4.6-sonnet&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; deepAgent&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;agents&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; completed &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;conversation:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;407e65ad&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;service:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;CatalogService&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;duration:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;3.9s&#39;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;This is just the basics, scratching the surface. The plugin also has support
for defining an agent&#39;s identity, behaviour and skills in Markdown, plus a
human-in-the-loop feature. There&#39;s plenty of more advanced facilities too.&lt;/p&gt;
&lt;p&gt;But for now, so far so good!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Balancing context size and callable tool metadata with CAP&#39;s MCP adapter</title>
    <link href="https://qmacro.org/blog/posts/2026/08/23/balancing-context-size-and-callable-tool-metadata-with-caps-mcp-adapter/" />
    <updated>2026-08-23T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/08/23/balancing-context-size-and-callable-tool-metadata-with-caps-mcp-adapter/</id>
    <content type="html">&lt;p&gt;CAP &lt;a href=&quot;https://cap.cloud.sap/docs/guides/protocols/mcp&quot;&gt;supports the Model Context
Protocol&lt;/a&gt;, and treats it
beautifully as &amp;quot;just another protocol&amp;quot;. The support comes in the form of the
&lt;a href=&quot;https://github.com/cap-js/mcp&quot;&gt;@cap-js/mcp&lt;/a&gt; plugin, which has these &lt;a href=&quot;https://github.com/cap-js/mcp#feature-flags&quot;&gt;feature
flags&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;cds&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;mcp&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;per_action_tool&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;prefix&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;format&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cql&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this post I want to explore the &lt;code&gt;per_action_tool&lt;/code&gt; setting.&lt;/p&gt;
&lt;h2 id=&quot;sample-service&quot;&gt;Sample service&lt;/h2&gt;
&lt;p&gt;To illustrate, let&#39;s use the classic
&lt;a href=&quot;https://github.com/capire/bookshop&quot;&gt;capire/bookshop&lt;/a&gt; sample project which,
amongst other resources, has a service defined in &lt;code&gt;srv/cat-service.cds&lt;/code&gt; like
this:&lt;/p&gt;
&lt;pre class=&quot;language-cds&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cds&quot;&gt;&lt;span class=&quot;token using keyword&quot;&gt;using&lt;/span&gt; { sap.capire.bookshop &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;as&lt;/span&gt; my } &lt;span class=&quot;token from keyword&quot;&gt;from&lt;/span&gt; &#39;../db/schema&#39;;

&lt;span class=&quot;token keyword&quot;&gt;service&lt;/span&gt; CatalogService &lt;span class=&quot;token annotation important&quot;&gt;@(path:&#39;browse&#39;)&lt;/span&gt; {

  &lt;span class=&quot;token block-comment comment&quot;&gt;/** For displaying lists of Books */&lt;/span&gt;
  &lt;span class=&quot;token annotation important&quot;&gt;@readonly&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;entity&lt;/span&gt; ListOfBooks &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token cdl-keyword keyword&quot;&gt;projection&lt;/span&gt; &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;on&lt;/span&gt; Books {
    *, currency.symbol &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;as&lt;/span&gt; currency,
  }
  excluding { descr };

  &lt;span class=&quot;token block-comment comment&quot;&gt;/** For display in details pages */&lt;/span&gt;
  &lt;span class=&quot;token annotation important&quot;&gt;@readonly&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;entity&lt;/span&gt; Books &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token cdl-keyword keyword&quot;&gt;projection&lt;/span&gt; &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;on&lt;/span&gt; my.Books {
    *, &lt;span class=&quot;token single-line-comment comment&quot;&gt;// all fields with the following denormalizations:&lt;/span&gt;
    author.name &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;as&lt;/span&gt; author,
    genre.name &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;as&lt;/span&gt; genre,
  } excluding { createdBy, modifiedBy };

  &lt;span class=&quot;token annotation important&quot;&gt;@requires:&lt;/span&gt; &#39;authenticated-user&#39;
  &lt;span class=&quot;token keyword&quot;&gt;action&lt;/span&gt; submitOrder ( book: Books:ID, quantity: &lt;span class=&quot;token type builtin&quot;&gt;Integer &lt;/span&gt;);
}

&lt;span class=&quot;token single-line-comment comment&quot;&gt;// Serve via OData, HCQL and REST&lt;/span&gt;
annotate CatalogService with &lt;span class=&quot;token annotation important&quot;&gt;@odata&lt;/span&gt; &lt;span class=&quot;token annotation important&quot;&gt;@hcql&lt;/span&gt; &lt;span class=&quot;token annotation important&quot;&gt;@rest;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The service has:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;entities &lt;code&gt;ListOfBooks&lt;/code&gt; and &lt;code&gt;Books&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;an unbound action &lt;code&gt;submitOrder&lt;/code&gt; (for which authentication is needed)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We&#39;ll begin by adding the MCP adapter plugin to the project like this:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; @cap-js/mcp&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;extending-the-service-definition&quot;&gt;Extending the service definition&lt;/h3&gt;
&lt;p&gt;Extending the definition slightly will help us dig in and understand the different
approaches that we can control with &lt;code&gt;per_action_tool&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To keep things simple, let&#39;s just add content to the existing &lt;code&gt;srv/cat-service.cds&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;First, let&#39;s add a &lt;a href=&quot;https://cap.cloud.sap/docs/guides/protocols/mcp#adding-context-information&quot;&gt;doc
comment&lt;/a&gt;
to the &lt;code&gt;submitOrder&lt;/code&gt; action, so it looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-cds&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cds&quot;&gt;  &lt;span class=&quot;token annotation important&quot;&gt;@requires:&lt;/span&gt; &#39;authenticated-user&#39;
  &lt;span class=&quot;token block-comment comment&quot;&gt;/** Place an order for a given book, specifying quantity required */&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;action&lt;/span&gt; submitOrder ( book: Books:ID, quantity: &lt;span class=&quot;token type builtin&quot;&gt;Integer &lt;/span&gt;);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now let&#39;s define another action in the service, by adding this at the end of
the file:&lt;/p&gt;
&lt;pre class=&quot;language-cds&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cds&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;service&lt;/span&gt; CatalogService with {
  &lt;span class=&quot;token block-comment comment&quot;&gt;/** Return the total value of all stock */&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;action&lt;/span&gt; stockValue ();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, let&#39;s actually add the &lt;code&gt;@mcp&lt;/code&gt; annotation, on a further line at the
end of the file:&lt;/p&gt;
&lt;pre class=&quot;language-cds&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cds&quot;&gt;annotate CatalogService with &lt;span class=&quot;token annotation important&quot;&gt;@mcp;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;a-running-cap-server&quot;&gt;A running CAP server&lt;/h3&gt;
&lt;p&gt;We&#39;ll be running a CAP server, started with &lt;code&gt;DEBUG=mcp cds watch&lt;/code&gt;, throughout
the explorations here; the log output that we need to know about looks like
this:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;mcp&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; Adapter initialized &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; service&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;CatalogService&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; serving CatalogService &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;at:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&#39;/odata/v4/browse&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&#39;/rest/browse&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&#39;/hcql/browse&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&#39;/mcp/browse&#39;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;decl:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;srv/cat-service.cds:3&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;impl:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;srv/cat-service.js&#39;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;mcp&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; registering MCP services&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;CatalogService&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; server listening on &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;http://localhost:4004&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tells us that the MCP adapter is accessible at &lt;code&gt;http://localhost:4004/mcp/browse&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;inspector&quot;&gt;Inspector&lt;/h2&gt;
&lt;p&gt;To assist exploration, let&#39;s use the &lt;a href=&quot;https://github.com/modelcontextprotocol/inspector&quot;&gt;MCP
inspector&lt;/a&gt; tool, which can
be operated in GUI, TUI or CLI mode. We&#39;ll use the CLI mode here to keep things
simple.&lt;/p&gt;
&lt;p&gt;The basic inspector CLI call to connect to and interact with the MCP server provided
by the MCP adapter looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;npx @modelcontextprotocol/inspector &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--cli&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--header&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Authorization: Basic YWxpY2U6Cg==&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--transport&lt;/span&gt; http &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  --server-url http://localhost:4004/mcp/browse&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;plus some actual method, with the &lt;code&gt;--method&lt;/code&gt; option.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We&#39;re sending an auth header - the encoded value is &lt;code&gt;alice:&lt;/code&gt; (there&#39;s no
password) as &lt;code&gt;alice&lt;/code&gt; is one of the users available by default in the mocked
authentication strategy which is in effect by default when running in
development mode - see &lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/12/local-first-dev-with-cap-node-js-mocking-auth/&quot;&gt;Local-first dev with CAP Node.js - mocking
auth&lt;/a&gt;.
This is to address the &lt;code&gt;authenticated-user&lt;/code&gt; pseudo-role requirement for the
&lt;code&gt;submitOrder&lt;/code&gt; action later.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;tools-list&quot;&gt;Tools list&lt;/h2&gt;
&lt;p&gt;By default, the MCP adapter offers up to three tools per service annotated with
&lt;code&gt;@mcp&lt;/code&gt;, in response to the
&lt;a href=&quot;https://modelcontextprotocol.io/specification/2025-06-18/server/tools#listing-tools&quot;&gt;tools/list&lt;/a&gt;
request.&lt;/p&gt;
&lt;p&gt;We can see this with the inspector, using the basic CLI call plus &lt;code&gt;--method tools/list&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;npx @modelcontextprotocol/inspector &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--cli&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--header&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Authorization: Basic YWxpY2U6Cg==&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--transport&lt;/span&gt; http &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  --server-url http://localhost:4004/mcp/browse &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--method&lt;/span&gt; tools/list &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; tools.json&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This returns quite a bit of output, in JSON, so we&#39;re redirecting that to a
&lt;code&gt;tools.json&lt;/code&gt; file, where we can use &lt;code&gt;jq&lt;/code&gt; to explore it separately.&lt;/p&gt;
&lt;p&gt;Let&#39;s first reduce the JSON response to simply see what the tool names are and
how they&#39;re described:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;jq &lt;span class=&quot;token string&quot;&gt;&#39;[.tools[]|{(.name):.description}]|add&#39;&lt;/span&gt; tools.json&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Echoing Perl&#39;s &lt;a href=&quot;https://en.wiktionary.org/wiki/TMTOWTDI&quot;&gt;TMTOWTDI&lt;/a&gt; tradition,
one could also achieve the same result with the jq expression
&lt;code&gt;.tools|map({(.name):.description})|add&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This produces:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;describe&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Describe the data model of CatalogService service. Returns an overview of all entities and actions with descriptions. Specify &#39;entity&#39; to get element details, or &#39;action&#39; to get parameter details.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;query&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Query any entity in CatalogService service.Ensure to first use the `describe` tool to discover an entity&#39;s available fields.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;call&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Call an unbound action or function in CatalogService service. Use describe to discover available actions and their parameters.&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;describe&lt;/code&gt; and &lt;code&gt;query&lt;/code&gt; tools are fairly standard and nearly always supplied
(except when the caller has no access). The &lt;code&gt;call&lt;/code&gt; tool, returned when there
are actions or functions available, is the focus of this post and of the
&lt;code&gt;per_action_tool&lt;/code&gt; setting.&lt;/p&gt;
&lt;h2 id=&quot;the-generic-call-tool&quot;&gt;The generic call tool&lt;/h2&gt;
&lt;p&gt;Let&#39;s dig in to the details supplied with the &lt;code&gt;call&lt;/code&gt; tool. With:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;jq &lt;span class=&quot;token string&quot;&gt;&#39;.tools[]|select(.name==&quot;call&quot;)&#39;&lt;/span&gt; tools.json&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we see this output:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;call&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Call an unbound action or function in CatalogService service. Use describe to discover available actions and their parameters.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;inputSchema&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;action&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;enum&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
          &lt;span class=&quot;token string&quot;&gt;&quot;submitOrder&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token string&quot;&gt;&quot;stockValue&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;The action or function to call&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;parameters&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Parameters for the action. Use describe to see available parameters.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;additionalProperties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;required&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;action&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://json-schema.org/draft/2020-12/schema&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;annotations&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;readOnlyHint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;destructiveHint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;idempotentHint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;openWorldHint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we &lt;a href=&quot;https://qmacro.org/blog/posts/2017/02/19/the-beauty-of-recursion-and-list-machinery/#initial-recognition&quot;&gt;stare
at&lt;/a&gt;
this for a moment, we see that it&#39;s rather generic.&lt;/p&gt;
&lt;p&gt;Moreover, the description includes instructions that require the use of the
&lt;code&gt;describe&lt;/code&gt; tool first, before working out which (if any) call can be made. The
info we have in our doc comments (&amp;quot;Place an order for a given book,
specifying quantity required&amp;quot; and &amp;quot;Return the total value of all stock&amp;quot;) aren&#39;t
even surfaced here.&lt;/p&gt;
&lt;p&gt;All we have is a simple enumerated list of action names in &lt;code&gt;inputSchema.properties.enum&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;per-action-tools&quot;&gt;Per-action tools&lt;/h2&gt;
&lt;p&gt;Let&#39;s now contrast that &lt;em&gt;&amp;quot;describe&amp;quot; + &amp;quot;query&amp;quot; + single &amp;quot;call&amp;quot; tool&lt;/em&gt; set, with what we get
if we set the MCP adapter plugin&#39;s &lt;code&gt;per_action_tool&lt;/code&gt; feature flag to &lt;code&gt;true&lt;/code&gt;. We can do
that in many ways; let&#39;s keep things simple and add a &lt;code&gt;mcp.per_action_tool&lt;/code&gt; property
to the &lt;code&gt;.cdsrc.yaml&lt;/code&gt; file that already exists in the project, like this:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;cds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;mcp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;per_action_tool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;requires&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;&quot;[production]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;auth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; mocked &lt;span class=&quot;token comment&quot;&gt;# as a sample app run with mocked auth also in production&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When we restart the CAP server, and make a &lt;code&gt;tools/list&lt;/code&gt; request again,
we get the same response detail for the &lt;code&gt;describe&lt;/code&gt; and &lt;code&gt;query&lt;/code&gt;
tools, but the detail for the actions available looks completely different.&lt;/p&gt;
&lt;p&gt;Let&#39;s examine the JSON output again. First, with
&lt;code&gt;.tools|map({(.name):.description})|add&lt;/code&gt; we can see the tools and their
descriptions:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;describe&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Describe the data model of CatalogService service. Returns an overview of all entities and actions with descriptions. Specify &#39;entity&#39; to get element details, or &#39;action&#39; to get parameter details.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;query&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Query any entity in CatalogService service.Ensure to first use the `describe` tool to discover an entity&#39;s available fields.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;submitOrder&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Call action submitOrder in CatalogService&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;stockValue&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Return the total value of all stock&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This time, instead of the generic &lt;code&gt;call&lt;/code&gt; tool, we get individual tools,
complete with unique descriptions (from the doc comments).&lt;/p&gt;
&lt;p&gt;Also, note that the simple &lt;code&gt;call&lt;/code&gt; tool info earlier didn&#39;t have any parameter
detail for either of the actual actions; instead, there was an instruction to
&amp;quot;use describe to see available parameters&amp;quot;.&lt;/p&gt;
&lt;p&gt;But now, for each callable action, all the parameter details are available. Let&#39;s
look at the details for the &lt;code&gt;submitOrder&lt;/code&gt; action, with &lt;code&gt;.tools[2]&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;submitOrder&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Call action submitOrder in CatalogService&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;inputSchema&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;properties&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;book&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;integer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;minimum&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;-9007199254740991&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;maximum&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9007199254740991&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;quantity&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;integer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;minimum&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;-9007199254740991&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;maximum&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9007199254740991&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;$schema&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://json-schema.org/draft/2020-12/schema&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;annotations&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;readOnlyHint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;destructiveHint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;idempotentHint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;openWorldHint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The included &lt;code&gt;inputSchema&lt;/code&gt; describes the two properties required (&lt;code&gt;book&lt;/code&gt; and &lt;code&gt;quantity&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;So in this case, no pre-action-call discovery step is needed, no extra describe
step need be executed just to find out what these actions are, whether they
might be useful and how to call them.&lt;/p&gt;
&lt;h2 id=&quot;comparing-the-options&quot;&gt;Comparing the options&lt;/h2&gt;
&lt;p&gt;Which option is better? &lt;code&gt;per_action_tool: true&lt;/code&gt; or &lt;code&gt;per_action_tool: false&lt;/code&gt;?
Well, that depends of course. There&#39;s a balance to be had.&lt;/p&gt;
&lt;p&gt;Returning a single generic &lt;code&gt;call&lt;/code&gt; tool, merely flagging that there&#39;s a facility
to make calls to specific actions and functions, with a simple list of them,
makes for quite a concise response. This in turn means that the size of the
context where this is stored remains relatively small. But the downside is that
there are going to be extra roundtrips required to accomplish anything
meaningful, as a &lt;code&gt;describe&lt;/code&gt; call is necessary to find out more.&lt;/p&gt;
&lt;p&gt;Describing separate &lt;code&gt;call&lt;/code&gt;-type tools means that the context is potentially
going to get much larger, if there are many actions and functions available.
However the upside is that they&#39;re likely immediately comprehensible and
usable.&lt;/p&gt;
&lt;p&gt;The MCP adapter plugin team has taken the decision to default to &amp;quot;safe&amp;quot; and
simple, to avoid exploding the context size unexpectedly, which makes sense. In
other words, the default is &lt;code&gt;per_action_tool: false&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Only you can make the decision to change the value for that feature flag, based
on your service definitions, and other circumstances. Certainly if you only
have a small number of actions, then it&#39;s worth considering turning on the
&lt;code&gt;per_action_tool&lt;/code&gt; flag. But if you have many, you may wish not to.&lt;/p&gt;
&lt;p&gt;But now at least you know what the flag does, why, and how it affects things.&lt;/p&gt;
&lt;h2 id=&quot;further-info&quot;&gt;Further info&lt;/h2&gt;
&lt;p&gt;This topic is also covered in &lt;a href=&quot;https://www.youtube.com/watch?v=Nu_bEVFM7DM&quot;&gt;Part 3 of CAP in the age of
AI&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Knowledge and netiquette in today&#39;s AI era</title>
    <link href="https://qmacro.org/blog/posts/2026/07/29/knowledge-and-netiquette-in-todays-ai-era/" />
    <updated>2026-07-29T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/07/29/knowledge-and-netiquette-in-todays-ai-era/</id>
    <content type="html">&lt;p&gt;I&#39;m walking in the cool mornings at the moment, as the problem with my right
knee is preventing me from running right now, which is driving me bonkers.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://qmacro.org/images/2026/07/morning-from-the-stern.jpg&quot; alt=&quot;View from the narrowboat stern this morning just before I set off on the walk&quot;&gt;
&lt;em&gt;View from the narrowboat stern this morning just before I set off on the walk.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;On the walk this morning, I listened to a couple of episodes from two great
podcasts I&#39;m subscribed to - &lt;a href=&quot;https://hanselminutes.com/&quot;&gt;Hanselminutes&lt;/a&gt; and
&lt;a href=&quot;https://softskills.audio/&quot;&gt;Soft Skills Engineering&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;knowledge-engineering-and-lifecycle-management&quot;&gt;Knowledge engineering and lifecycle management&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://hanselminutes.com/1051/stack-overflow-for-the-agent-era-with-vp-of-product-alex-lato&quot;&gt;Stack Overflow for the Agent Era - with VP of Product Alex
Lato&lt;/a&gt;,
Scott Hanselman talks to Alex Lato about how Stack Overflow is evolving, driven
by, and perhaps driven towards, the agent substrate. It&#39;s a fascinating
conversation between two experienced folks, and well worth a complete listen.
What I took from this conversation is that we may see a new knowledge-related
discipline emerging, or at least a stronger focus in that direction.&lt;/p&gt;
&lt;p&gt;Scott and Alex talked a lot about knowledge provenance, reliability,
attribution and ranking, which made me wonder about what knowledge engineering,
perhaps knowledge lifecycle management, might look like today and tomorrow.
This knowledge, and how agents source, relay, condense, combine and share it,
is originally from the hard work of folks on Stack Overflow and in other
communities sharing what they know, but how will that evolve when the layers of
reuse coalesce over time?&lt;/p&gt;
&lt;p&gt;One other fascinating aspect that Alex shared, and Scott picked up, is that in
Stack Overflow&#39;s new venture here, agents, and their activities, are ultimately
and strongly tied to human &amp;quot;owners&amp;quot;, with the provenance - but more importantly
reputation - that is part of that association.&lt;/p&gt;
&lt;h2 id=&quot;netiquette-and-how-our-connections-are-changing&quot;&gt;Netiquette and how our connections are changing&lt;/h2&gt;
&lt;p&gt;In Soft Skills Engineering&#39;s &lt;a href=&quot;https://softskills.audio/2026/07/06/episode-520-i-came-back-to-my-former-team-and-was-shocked-by-ai-and-my-team-does-not-care-at-all-about-the-code/&quot;&gt;Episode
520&lt;/a&gt;,
hosts Dave Smith and Jamison Dance are entertaining and fun to listen to as
usual, and the word &amp;quot;netiquette&amp;quot; is brought up in the context of what one
should and should not do in today&#39;s era of AI assisted work.&lt;/p&gt;
&lt;p&gt;Netiquette was originally an umbrella term for how to behave in the brave new
world of Internet-based communication - for example how and when to use the
To:, Cc: and Bcc: in email correspondence (on which &lt;a href=&quot;https://qmacro.org/blog/posts/2014/11/14/addressing-emails/&quot;&gt;I have
thoughts&lt;/a&gt; too), when to reply, and
how formal, or not, one should be, in various situations. That concept of &amp;quot;how
to behave&amp;quot; surfaces in this conversation again where Dave and Jamison talk
about their (and others&#39;) experiences with folks copy-pasting wads of
generative AI output to each other, sometimes without even reading it
themselves.&lt;/p&gt;
&lt;p&gt;Following that train of thought, they reach a conclusion that is not an
entirely pleasant one, that the LLM facilities we have at our fingertips today
is causing the death of the human connection, a connection that originally
evolved (in our tech workplaces) almost as a by-product of collaborating on
design and code, to get it right. When we have LLMs do a lot of that for us,
where&#39;s the context in which we maintain that loose but essential human
connection - the shared jokes, the gently snarky but well-meaning asides?&lt;/p&gt;
&lt;p&gt;If you&#39;re not subscribed to these podcasts, I recommend you remedy that today!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Timeless principles, agnostic design and the power of CAP&#39;s abstractions</title>
    <link href="https://qmacro.org/blog/posts/2026/07/24/timeless-principles-agnostic-design-and-the-power-of-caps-abstractions/" />
    <updated>2026-07-24T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/07/24/timeless-principles-agnostic-design-and-the-power-of-caps-abstractions/</id>
    <content type="html">&lt;p&gt;I wrote recently about Hexagonal Architecture, alternatively known as Ports &amp;amp;
Adapters, in &lt;a href=&quot;https://qmacro.org/blog/posts/2026/06/04/book-overflow-and-two-architectural-patterns-in-cap/#ports-and-adapters&quot;&gt;Book Overflow and two architectural patterns in
CAP&lt;/a&gt;.
The core idea is based on having a deliberately agnostic approach to
mechanisms, resources and services beyond - located in the outer concentric
circles, as it were - a given core service.&lt;/p&gt;
&lt;p&gt;Think of this in a similar way to &amp;quot;late cut&amp;quot; integration, where the actual
location, shape of, and connection to a required service is left until the
last minute.&lt;/p&gt;
&lt;p&gt;The agnostic design approach is not new, and indeed as Daniel mentions in his
keynote, has in the past been referred to as &amp;quot;minimal assumptions&amp;quot;, which crops
up in various disciplines, including statistics &amp;amp; data analysis, where it
conveys the approach of &amp;quot;&lt;em&gt;deriving valid conclusions using the fewest possible
restrictive parameters&lt;/em&gt;&amp;quot;&lt;a href=&quot;https://qmacro.org/blog/posts/2026/07/24/timeless-principles-agnostic-design-and-the-power-of-caps-abstractions/#footnotes&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This approach brings many advantages, not least the ability for CAP developers
to enjoy a tight and rapid development loop, where
&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/11/local-first-dev-with-cap-node-js/&quot;&gt;local-first&lt;/a&gt; is the
mantra, and mocking plus remote proxies are key enablers.&lt;/p&gt;
&lt;p&gt;Moreover it allows us to shift &lt;em&gt;left&lt;/em&gt; the important business of design,
including auth, consumption nuances and extended domain design, exactly because
we can shift &lt;em&gt;right&lt;/em&gt; the dirty work of connectivity and gnarly setups.&lt;/p&gt;
&lt;p&gt;But that&#39;s only one half of the story. The other half is that, right from the
get-go, we&#39;re ready to adapt and adopt new services, or different endpoint
locations, because we haven&#39;t tightly coupled our app or service design with a
specific technology or protocol.&lt;/p&gt;
&lt;h2 id=&quot;the-wonder-of-cds-service-bindings&quot;&gt;The wonder of cds.service.bindings&lt;/h2&gt;
&lt;p&gt;To illustrate this, I want to convey the wonder of one of Daniel&#39;s live demos
in the keynote. Indeed, this blog post was triggered by something very
specific, when Daniel accessed &lt;code&gt;cds.service.bindings&lt;/code&gt; in the cds REPL.&lt;/p&gt;
&lt;p&gt;I have talked about the local service binding registry (&lt;code&gt;~/.cds-services.json&lt;/code&gt;)
and explained its purpose, in many places, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/SAP-samples/cap-local-development-workshop&quot;&gt;CAP local
development&lt;/a&gt;
(workshop)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/SAP-samples/cap-service-integration-codejam&quot;&gt;Service integration with SAP Cloud Application Programming
Model&lt;/a&gt;
(CodeJam)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/SAP-samples/cap-tour-hands-on&quot;&gt;A hands-on tour of CAP&lt;/a&gt;
(CodeJam)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&#39;s break down what we mean by &amp;quot;local service binding registry&amp;quot;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;local: it&#39;s local to my machine, both highlighted and constrained by the
location of this file, the developer user&#39;s home
directory&lt;a href=&quot;https://qmacro.org/blog/posts/2026/07/24/timeless-principles-agnostic-design-and-the-power-of-caps-abstractions/#footnotes&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; - you can&#39;t get much more &amp;quot;my machine&amp;quot;
specific than that!&lt;/li&gt;
&lt;li&gt;service: required services, that are likely going to be remote in a
production scenario&lt;/li&gt;
&lt;li&gt;binding: information that is needed to be able to connect and authenticate
with such services, such as URL &amp;amp; credentials, often collected into a
&lt;a href=&quot;https://help.sap.com/docs/excise-tax-management/administration/sap-btp-creating-and-configuring-destination&quot;&gt;destination&lt;/a&gt;
in production scenarios&lt;/li&gt;
&lt;li&gt;registry: a sort of table of contents, or list of what&#39;s currently available&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Such a local registry is at the heart of how agnostic design&#39;s innermost set
of concentric circles (the local machine) can function in CAP.&lt;/p&gt;
&lt;p&gt;Seeing Daniel retrieve this binding information directly in the cds REPL was a
magic moment for me. It both elevated the combined concepts I&#39;ve mentioned above,
plus made the registry content tangible and thus worthy of attention.&lt;/p&gt;
&lt;h2 id=&quot;exploring-the-first-two-circles&quot;&gt;Exploring the first two circles&lt;/h2&gt;
&lt;p&gt;Let&#39;s explore the two innermost circles&lt;a href=&quot;https://qmacro.org/blog/posts/2026/07/24/timeless-principles-agnostic-design-and-the-power-of-caps-abstractions/#footnotes&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;, the ones
&lt;em&gt;within&lt;/em&gt; the local machine.&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt; +--------------------------+
 |     external process     |
 | ************************ |
 | * +------------------+ * |
 | * | separate process | * |
 | * |  +------------+  | * |
 | * |  | in-process |  | * |
 | * |  |            |  | * |
 | * |  +------------+  | *&lt;---- local machine
 | * +------------------+ * |
 | ************************ |
 +--------------------------+&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can run a single CAP server, that will serve one or more services, via one
or more protocols. That&#39;s denoted by the core &amp;quot;in-process&amp;quot; circle in this
diagram here. When we have a required service without
service bindings available, these are mocked also by the same CAP server.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;At this point I often refer to the help text for the &lt;code&gt;--with-mocks&lt;/code&gt; option
for &lt;code&gt;cds serve&lt;/code&gt; which goes like this (emphasis mine):&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Use this in combination with the variants serving multiple services.
&lt;strong&gt;It starts in-process mock services for all required services configured
in &lt;code&gt;package.json#cds.requires&lt;/code&gt;, which don&#39;t have external bindings
in the current process environment.&lt;/strong&gt;
Note that by default, this feature is disabled in production and must be
enabled with configuration &lt;code&gt;features.mocked_bindings=true&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We can run multiple CAP servers on the same machine, choosing different
ports&lt;a href=&quot;https://qmacro.org/blog/posts/2026/07/24/timeless-principles-agnostic-design-and-the-power-of-caps-abstractions/#footnotes&quot;&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt;. From the perspective of the &amp;quot;in-process&amp;quot;
innermost circle, the next circle out, marked &amp;quot;separate process&amp;quot;, represents
these other CAP servers.&lt;/p&gt;
&lt;p&gt;This &amp;quot;local machine&amp;quot; universe, combined with CAP&#39;s local-first affordances,
is exactly what we need to experiment with agnostic design here.&lt;/p&gt;
&lt;p&gt;This demo follows roughly the same path as Daniel took in his keynote, with
some slight variations.&lt;/p&gt;
&lt;h3 id=&quot;start-monitoring-the-local-service-binding-registry&quot;&gt;Start monitoring the local service binding registry&lt;/h3&gt;
&lt;p&gt;It&#39;s helpful to see what happens as things progress, so let&#39;s use one terminal
window to keep an eye on the local service binding registry&#39;s contents. Here&#39;s
how I would do it:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; ~/.cds-services.json &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;watch&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; jq &lt;span class=&quot;token parameter variable&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; ~/.cds-services.json&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;I use &lt;code&gt;touch&lt;/code&gt; first to make sure the file exists before trying to monitor it;
this command will create the file, empty, if it doesn&#39;t. If it has already
been populated with information from previously running CAP servers (that have
since been stopped) then it may already contain some empty registry structure
that looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;cds&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;provides&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;servers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;create-a-simple-cap-project-a&quot;&gt;Create a simple CAP project A&lt;/h3&gt;
&lt;p&gt;First, let&#39;s create a simple &lt;code&gt;tiny-sample&lt;/code&gt; facet based CAP project &amp;quot;A&amp;quot; then
immediately launch a cds REPL and have the CAP server start
up&lt;a href=&quot;https://qmacro.org/blog/posts/2026/07/24/timeless-principles-agnostic-design-and-the-power-of-caps-abstractions/#footnotes&quot;&gt;&lt;sup&gt;5&lt;/sup&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;cds init &lt;span class=&quot;token parameter variable&quot;&gt;--add&lt;/span&gt; tiny-sample proj-A &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; cds repl &lt;span class=&quot;token parameter variable&quot;&gt;--run&lt;/span&gt; proj-A&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Log output like this will be emitted:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token property&quot;&gt;Adding facet:&lt;/span&gt; tiny&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;sample

Successfully initialized CAP project
&lt;span class=&quot;token property&quot;&gt;Continue with:&lt;/span&gt; code proj&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;A

Welcome to cds repl &lt;span class=&quot;token number&quot;&gt;v10.0.3&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; using bindings from&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; registry&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;~/.cds-services.json&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; loaded model from &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; file&lt;span class=&quot;token operator&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token operator&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;

  proj&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;srv&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;cat&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;service&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cds

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; connect to db &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; sqlite &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; database&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;:memory:&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; init from proj&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;db&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;CatalogService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Books&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;csv
&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; successfully deployed to in&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;memory database&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; using auth strategy &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; kind&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;mocked&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; serving CatalogService &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;at:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/odata/v4/catalog&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;decl:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;proj-A/srv/cat-service.cds:1&#39;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; server listening on &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;http://localhost:33475&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; server &lt;span class=&quot;token number&quot;&gt;v10.0.3&lt;/span&gt; launched in &lt;span class=&quot;token number&quot;&gt;209&lt;/span&gt; ms
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; terminate with &lt;span class=&quot;token operator&quot;&gt;^&lt;/span&gt;C &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token separator comment&quot;&gt;------------------------------------------------------------------------&lt;/span&gt;
Following variables are made available in your repl&#39;s global context&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;

&lt;span class=&quot;token property&quot;&gt;from cds.entities:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token property&quot;&gt;from cds.services:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  db&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  CatalogService&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;

Simply type e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;g&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; CatalogService in the prompt to use the respective objects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So far, so (very) good. Notice that the CAP server is started on a random port,
which is the default behaviour when running in a REPL context (as it&#39;s
effectively more of a &amp;quot;throwaway&amp;quot; server that might be spun up to run some
tests against).&lt;/p&gt;
&lt;p&gt;Notice also that there&#39;s a service called &lt;code&gt;CatalogService&lt;/code&gt; that&#39;s available.&lt;/p&gt;
&lt;h3 id=&quot;check-the-local-service-binding-registry&quot;&gt;Check the local service binding registry&lt;/h3&gt;
&lt;p&gt;In the registry, we now see something like this:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;cds&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;provides&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;CatalogService&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;endpoints&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;odata&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/odata/v4/catalog&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;58557&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;servers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;58557&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;file:///tmp/proj-A&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://localhost:33475&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tells us (and any CAP server running in the same binding context, i.e.
this local machine) that there&#39;s a service called &lt;code&gt;CatalogService&lt;/code&gt; that is
provided. There&#39;s information on what the endpoints are, and what protocols
these endpoints speak, and also the URL. In other words, this is the binding
context for the &lt;code&gt;CatalogService&lt;/code&gt; that is listed as being provided (note the
&lt;code&gt;cds.provides&lt;/code&gt; property that contains it)!&lt;/p&gt;
&lt;h3 id=&quot;connect-and-consume-catalogservice-locally&quot;&gt;Connect and consume CatalogService locally&lt;/h3&gt;
&lt;p&gt;Within the REPL, if we now have a quick look at the &lt;code&gt;CatalogService&lt;/code&gt;, we see
that it&#39;s an instance of the &lt;code&gt;ApplicationService&lt;/code&gt; class, effectively a locally
available service:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; CatalogService
ApplicationService &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;handlers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;EventHandlers&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;CatalogService&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;app-service&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/odata/v4/catalog&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&#39;$linkProviders&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Array&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can consume that service directly, whereupon we&#39;ll get the result we
probably expect:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; CatalogService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Books&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Wuthering Heights&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Emily Brontë&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Jane Eyre&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Charlotte Brontë&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;The Raven&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Edgar Allen Poe&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Eleonora&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Edgar Allen Poe&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Catweazle&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Richard Carpenter&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can be explicit and &lt;a href=&quot;https://cap.cloud.sap/docs/node.js/core-services#connecting-to-required-services--cdsconnect&quot;&gt;connect to&lt;/a&gt; the service, a &amp;quot;required&amp;quot; service, like this, too:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; catsrv &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;connect&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;CatalogService&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
ApplicationService &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;handlers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;EventHandlers&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;CatalogService&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;app-service&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/odata/v4/catalog&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&#39;$linkProviders&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Array&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We effectively get the same &lt;code&gt;ApplicationService&lt;/code&gt; instance, and can use it in
the same way:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; catsrv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Books&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Wuthering Heights&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Emily Brontë&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Jane Eyre&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Charlotte Brontë&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;The Raven&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Edgar Allen Poe&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Eleonora&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Edgar Allen Poe&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Catweazle&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Richard Carpenter&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;consume-the-provided-service-from-elsewhere&quot;&gt;Consume the provided service from elsewhere&lt;/h2&gt;
&lt;p&gt;We don&#39;t even need to set up a second project to require (consume) this
provided service, we can just start a second cds REPL session and do everything
there.&lt;/p&gt;
&lt;p&gt;While keeping the current cds REPL session open, let&#39;s start a second cds REPL
session in a new terminal window. This should represent a distinctly separate
CAP consumer context and so let&#39;s start this second cds REPL session
completely separate from the &lt;code&gt;proj-A/&lt;/code&gt; area to emphasise that point. Daniel used
his home directory for that, so let&#39;s do that too:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; ~ &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; cds repl&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;fetch-the-service-bindings&quot;&gt;Fetch the service bindings&lt;/h4&gt;
&lt;p&gt;In the session that we get, which is announced like this:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Welcome to cds repl v10.0.3
&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we can access the service bindings, like this:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;service&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bindings&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This fetches the service bindings from the registry and makes them available in
the current process:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; using bindings from&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; registry&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;~/.cds-services.json&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
Bindings &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;provides:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;CatalogService:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; endpoints&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; odata&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/odata/v4/catalog&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; server&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;58557&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;servers:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&#39;58557&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; root&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;file:///tmp/proj-A&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;http://localhost:33475&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We even see that log line familiar to us from our &lt;code&gt;cds watch&lt;/code&gt; sessions, being
explicit about from where the bindings are being fetched:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; using bindings from&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; registry&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;~/.cds-services.json&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;connect-to-the-service&quot;&gt;Connect to the service&lt;/h4&gt;
&lt;p&gt;Like we did in the other cds REPL session, let&#39;s now use &lt;code&gt;cds.connect.to&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; cs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;connect&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;CatalogService&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
RemoteService &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;handlers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;EventHandlers&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;CatalogService&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;odata&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;requestTimeout&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;csrf&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;csrfInBatch&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This time, it&#39;s not an instance of the &lt;code&gt;ApplicationService&lt;/code&gt; class, it&#39;s an
instance of the &lt;code&gt;RemoteService&lt;/code&gt; class!&lt;/p&gt;
&lt;h4 id=&quot;send-a-query-to-the-service&quot;&gt;Send a query to the service&lt;/h4&gt;
&lt;p&gt;What&#39;s more, we can interact with that service ... as if it were local:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Books&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Wuthering Heights&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Emily Brontë&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Jane Eyre&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Charlotte Brontë&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;The Raven&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Edgar Allen Poe&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Eleonora&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Edgar Allen Poe&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Catweazle&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Richard Carpenter&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wham!&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;Going back to the concentric circles, this is a effectively an example of the
two that are within the confines of the local machine. One, the provided
service, exists as if it were remote (with a URL) in the eyes of the consuming
service (or REPL context here).&lt;/p&gt;
&lt;p&gt;CAP&#39;s adoption of minimal assumptions in service provision and consumption is
so complete that the lines become blurred between local and remote, thanks to
the power of remote proxies that do the heavy lifting of query transport across
the wire for us.&lt;/p&gt;
&lt;p&gt;This really is hard evidence of one of CAP&#39;s &amp;quot;magic made simple&amp;quot; moments, and
is explained further in the &lt;a href=&quot;https://cap.cloud.sap/docs/get-started/bookshop#cap-level-integration&quot;&gt;CAP-level
Integration&lt;/a&gt;
section of the Bookshop topic in Capire.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;See &lt;a href=&quot;https://www.tandfonline.com/doi/abs/10.1080/01621459.1962.10500545&quot;&gt;Non-Linear Regression with Minimal
Assumptions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The symbol for a user&#39;s home directory is the tilde (&lt;code&gt;~&lt;/code&gt;). I&#39;m guessing some
of you know why it&#39;s this symbol, but for those of you who don&#39;t, have a
look at the keyboard of the &lt;a href=&quot;https://en.wikipedia.org/wiki/ADM-3A&quot;&gt;ADM-3A&lt;/a&gt;
terminal, specifically in the top right. &lt;a href=&quot;https://en.wikipedia.org/wiki/ADM-3A&quot;&gt;Bill
Joy&lt;/a&gt;, erstwhile employee of Sun and
perhaps more importantly creator of both &lt;code&gt;vi&lt;/code&gt; and the C Shell (&lt;code&gt;csh&lt;/code&gt;), used
an ADM-3A and it was in the C Shell where the tilde came to represent a
user&#39;s home directory.&lt;/p&gt;
&lt;p&gt;Also on that same key is the caret (&lt;code&gt;^&lt;/code&gt;), which also represents &amp;quot;home&amp;quot;
(beginning of a line) in regular expression dialects. Coincidence? I think
not! :-)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://qmacro.org/images/2026/07/adm-3a-home-key.png&quot; alt=&quot;ADM-3A home key&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;OK, it may not have escaped your notice that these are not circles. Just
pretend they are.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It&#39;s the concept of a &lt;a href=&quot;https://en.wikipedia.org/wiki/Network_socket&quot;&gt;socket&lt;/a&gt;
that we must bear in mind, which is the combination of protocol, address
(hostname / IP) and port. But that&#39;s a story for another time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We can actually just specify the project location as a single argument and
the same thing will happen: &lt;code&gt;cds repl proj-A&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</content>
  </entry>
  <entry>
    <title>reCAP 2026 talk resources</title>
    <link href="https://qmacro.org/blog/posts/2026/07/15/recap-2026-talk-resources/" />
    <updated>2026-07-15T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/07/15/recap-2026-talk-resources/</id>
    <content type="html">&lt;p&gt;At &lt;a href=&quot;https://recap-conf.dev/&quot;&gt;reCAP&lt;/a&gt; this year, I was honoured to share a talk
slot with &lt;a href=&quot;https://www.linkedin.com/in/patrice-bender-64a816118/&quot;&gt;Patrice
Bender&lt;/a&gt;, a good friend
and adjacent colleague from the CAP Compiler team, and cohost / copresenter on
the &lt;a href=&quot;https://qmacro.org/blog/posts/2025/12/09/a-new-hands-on-sap-dev-mini-series-on-the-core-expression-language-in-cds/&quot;&gt;Hands-on SAP Dev mini-series on the core expression language in
CDS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://recap-conf.dev/program.html&quot;&gt;talk&lt;/a&gt; was titled &lt;strong&gt;Expressions
and Abstractions - Two Developer Superpowers in CAP&lt;/strong&gt;, with the following
overview:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Today we need to be more efficient and concise than ever, stop writing
code we don&#39;t need to, and avoid tasks that slow down our development
loops, letting the framework do the heavy lifting for us. In this
session we&#39;ll demonstrate two different affordances that enable that.
First, we&#39;ll show the power of expressions, what they are, how and
where they can be used, and why you should know about them. Then we&#39;ll
show how mocking abstracts us from the tedium and ceremony, allowing us
to iterate fast on data, auth, messaging and remote services during
development.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Whether you watched the talk at reCAP in person, or remotely, please consider
filling in the short &lt;a href=&quot;https://docs.google.com/forms/d/e/1FAIpQLSc88GKiyicSBTOmM8Hgl5wPoVC8Tvc9WbiaHfa3sg9itPRiFg/viewform?pli=1&quot;&gt;feedback
form&lt;/a&gt;.
Thanks!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here are some resources relating to the two parts.&lt;/p&gt;
&lt;h2 id=&quot;expressions&quot;&gt;Expressions&lt;/h2&gt;
&lt;p&gt;The demo resources used in this part of the talk are available in the repo
&lt;a href=&quot;https://github.com/patricebender/cxl-bookshop&quot;&gt;cxl-bookshop&lt;/a&gt; that is an
extended bookshop you can clone, open in &lt;code&gt;cds repl&lt;/code&gt;, and use to try everything
shown live.&lt;/p&gt;
&lt;p&gt;The talk is based on the 7-part Hands-on SAP Dev mini-series &lt;a href=&quot;https://youtube.com/playlist?list=PL6RpkC85SLQCEU8XcyqnA5wYEZGxMPm6B&quot;&gt;Under the hood:
CDS Expressions in
CAP&lt;/a&gt;,
with our written notes accompanying it, starting with &lt;a href=&quot;https://qmacro.org/blog/posts/2026/03/05/cds-expressions-in-cap-notes-on-part-1/&quot;&gt;Part
1&lt;/a&gt;.
For the reference, including syntax diagrams that show what an expression can
contain, see &lt;a href=&quot;https://cap.cloud.sap/docs/cds/cxl#expressions-expr&quot;&gt;the CXL topic in
Capire&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;abstractions&quot;&gt;Abstractions&lt;/h2&gt;
&lt;p&gt;The demo resources used in this part of the talk are available in the repo
&lt;a href=&quot;https://github.com/qmacro/cap-nodejs-local-first-development&quot;&gt;cap-nodejs-local-first-development&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/11/local-first-dev-with-cap-node-js/&quot;&gt;Local-first dev with CAP
Node.js&lt;/a&gt; series
of blog posts covers mocking of
&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/11/local-first-dev-with-cap-node-js-mocking-data/&quot;&gt;data&lt;/a&gt;,
&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/12/local-first-dev-with-cap-node-js-mocking-auth/&quot;&gt;auth&lt;/a&gt;,
&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/13/local-first-dev-with-cap-node-js-mocking-remote-services/&quot;&gt;remote
services&lt;/a&gt;
and
&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/15/local-first-dev-with-cap-node-js-mocking-messaging/&quot;&gt;messaging&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The blog post &lt;a href=&quot;https://qmacro.org/blog/posts/2026/06/19/cap-service-authentication-at-design-time-and-in-production/&quot;&gt;CAP service authentication at design time and in
production&lt;/a&gt;
covers the &lt;code&gt;restrict_all_services&lt;/code&gt; setting.&lt;/p&gt;
&lt;p&gt;In the content for the CodeJam &lt;a href=&quot;https://github.com/SAP-samples/cap-tour-hands-on&quot;&gt;A hands-on tour of
CAP&lt;/a&gt; there are deep and
detailed dive exercises on &lt;a href=&quot;https://github.com/SAP-samples/cap-tour-hands-on/blob/main/exercises/01/README.md&quot;&gt;mocking
auth&lt;/a&gt;
and &lt;a href=&quot;https://github.com/SAP-samples/cap-tour-hands-on/blob/main/exercises/02/README.md&quot;&gt;mocking
messaging&lt;/a&gt;.
At the end of each of these exercises are plenty of links to further
information including resources in &lt;a href=&quot;https://cap.cloud.sap/docs/&quot;&gt;Capire&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
</feed>