Using the built in summary feature when using ONLY paragraphs module for text
Well, looks like it is time again to answer my own question!

So, since the Metatag Module I want to also use is based on tokens anyway, I have managed to implement this using my own module which in turn just defines an additional custom token which in turn returns my desired summary. Here is what my current custom_summary_token.module code looks like right now (still work in progress):

use Drupal\Core\Render\BubbleableMetadata;
use Drupal\paragraphs\Entity\Paragraph;

function custom_summary_token_token_info(){
    $type = [
        'name' =&gt; t('Nodes'),
        'description' =&gt; t('Tokens related to individual nodes.'),
        'needs-data' =&gt; 'node'
    ];

    $node['custom_summary'] = array(
        'name' =&gt; t("Custom Summary"),
        'description' =&gt; t("Token for dynamically generating a node summary, depending on the content. Used for extracting text when not using standard body field, but only paragraphs."),
    );

    return [
        'types' =&gt; ['node' =&gt; $type],
        'tokens' =&gt; ['node' =&gt; $node],
    ];
}

function custom_summary_token_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata){

    if (!isset($data['node'])) { return; }

    $replacements = array();
    $node = $data['node'];

    if($type == 'node' &amp;&amp; !empty($node)) {

        foreach ($tokens as $name =&gt; $original) {

            switch ($name) {

                case 'custom_summary':

                    if (!empty($node-&gt;body-&gt;value)) {

                        $text = strip_tags($node-&gt;body-&gt;value);

                    } else if ($node-&gt;field_summary &amp;&amp; !empty($node-&gt;field_summary-&gt;getValue())) {

                        $text = $node-&gt;field_summary-&gt;getValue()[0]["value"];

                    } else if ($node-&gt;field_paragraph_test &amp;&amp; !empty($node-&gt;field_paragraph_test-&gt;getValue())) {

                        foreach ($node-&gt;field_paragraph_test-&gt;getValue() as $key =&gt; $value) {
                            $paragraph = FALSE;
                            if (!empty($value['entity'])) {
                                $paragraph = $value['entity']; // Use that, we're probably previewing.
                            } elseif (!empty($value['target_id'])) {
                                $paragraph = Paragraph::load($value['target_id']);
                            }
                            if ($paragraph !== FALSE &amp;&amp; $paragraph instanceof Paragraph &amp;&amp; $paragraph-&gt;getType() === "text") {
                                $text = strip_tags($paragraph-&gt;get('field_text_body')-&gt;value);
                                break;
                            }
                        }

                    }

                    if (strlen($text) &gt; 150) {
                        $text = substr($text, 0, 150)." ...";
                    }

                    $text = str_replace("&amp;nbsp;", " ", $text); // filter out artefact when editing with chrome
                    $replacements[$original] = $text;
                    break;
            }
        }
    }

    return $replacements;

}


So what this does in that tokens hook is (after checking that we have the right token of course) first to look for an ordinary default body text which is not empty. Simply because then this also works for my other (in this case also simpler) content types. Then, the code looks for a custom field named field_summary. Turned out that some users actually want to create a custom summary, so yeah now they can do that as well. For those who don't (the majority ...), the code then looks for the first paragraph instance which is also a text block (and not empty). Last but not least, tags are stripped, and the whole thing is truncated to 150 chars, with some "..." appended for good measure.

Now, I can use this just like any token in my Metatag setup: [node:custom_summary], and - with a little help from the twig tweak module - also in any template: 

{{ drupal_token('node:custom_summary', { node: node }) }}


Of course this implementation still might be too naive or there would be an even better way, also I am not sure how big the performance impact of such a solution is. But hey - at least this works!

What would you think?