That was kind of the idea of Unix. C was just a nicer from Assembly. You might write a performance-sensitive or low-level routine in C, much like you might drop to C when writing a Python library. But the high-level language of the system was the shell. The `dc` executable wasn't just meant to be a user-facing calculator program, it was also meant to be the system's "bignum" library. That was big-picture Unix. The syscalls and C were little-picture Unix.
This makes me think of PowerShell. Individual Cmdlets can be written in PowerShell itself or in any language that compiles to .Net IL, plus one has dire t access to the entire .Net framework.
PowerShell takes it a bit further: There is no "magic" built-in commands needed for e.g. manipulating current directory, environment variables etc. In PowerShell the cmdlets execute in-process and may have access to the session and it's state. Indeed all of the built-in cmdlets are just cmdlets defined not by the shell, but by the core modules
On the same line, let me recommend you a book: "The Design of the Unix Operating System," by Maurice J. Bach. If I am not mistaken, Mr. Bach was a member at Bell Labs.
My personal take on the book is that the kernel was meant to be a portable virtual machine, extensible through processes, and that those would be the building blocks of user applications for which the shell would act as glue.
In other words, the shell and the OS are separate because most of what we commonly call "the OS" may be interpreted as mere encapsulation of less versatile hardware architectures.
This 2013 thread shaped a lot of the way I think about Unix: https://news.ycombinator.com/item?id=6530180